Author: jfthomps Date: Wed Oct 20 16:17:19 2010 New Revision: 1025626 URL: http://svn.apache.org/viewvc?rev=1025626&view=rev Log: VCL-310 - remove jpgraph dependency replaced all jpgraph code with dojox's charting api
VCL-399 - add a dashboard where admins can see current state of VCL system added a new section to the site that is a page displaying various information about the site that gets updated with AJAX every n seconds; currently there are the following sections of information: Current Status - some general info Top 5 Images in Use Top 5 Long Term Images in Use Top Recent Computer Failures Top Recent Image Failures Block Allocation Status Past 12 Hours of Active Reservations statistics.php -removed require_once code for jpgraph -modified viewStatistics - when computing length of reservation, if $length ends up being < 0, set it to 0 -changed img references to jpgraphs to divs for dojox charts -added AJgetStatData -removed sendStatGraphDay -modified getStatGraphDayData - removed labels from $data, added xlabels to $data, added maxy to $data -removed statXaxisDayCallback -removed sendStatGraphHour -modified getStatGraphHourData - changed $data['points'] to be an array of data, added maxy to $data -renamed statXaxisHourCallback to statHourFromatX -removed sendStatGraphDayConUsers -modified getStatGraphDayConUsersData - removed labels from $data, added xlabels to $data, added maxy to $data -removed statXaxisDayConUsersCallback -removed sendStatGraphConBladeUser -modified getStatGraphConBladeUserData - removed labels from $data, added xlabels to $data, added maxy to $data -removed statXaxisConBladeUserCallback utils.php -modified initGlobals - added dashboard to section that does require_once based on the mode -modified getNavMenu - removed some old stuff left in there related to ecu $skin; added menu item for dashboard -modified getDojoHTML - added sections for viewstats and dashboard modes states.php -added dashboard to entry actions -added AJupdateDashboard and AJgetStatData to $noHTMLwrappers -removed statgraphday, statgraphhour, statgraphdayconcuruser, and statgraphdayconcurblade -added AJgetStatData -added dashboard section with modes dashboard and AJupdateDashboard js/code.js - modified errorHandler function reference - list of args were wrong; changed from 'type, error, data' to 'error, ioArgs'; changed args.dojoType to error.name (not sure if this is correct), changed alert to display better message dashboard.php - initial add to source control css/dashboard.css - initial add to source control js/dashboard.js - initial add to source control js/statistics.js - initial add to source control Added: incubator/vcl/trunk/web/.ht-inc/dashboard.php incubator/vcl/trunk/web/css/dashboard.css incubator/vcl/trunk/web/js/dashboard.js incubator/vcl/trunk/web/js/statistics.js Modified: incubator/vcl/trunk/web/.ht-inc/states.php incubator/vcl/trunk/web/.ht-inc/statistics.php incubator/vcl/trunk/web/.ht-inc/utils.php incubator/vcl/trunk/web/js/code.js Added: incubator/vcl/trunk/web/.ht-inc/dashboard.php URL: http://svn.apache.org/viewvc/incubator/vcl/trunk/web/.ht-inc/dashboard.php?rev=1025626&view=auto ============================================================================== --- incubator/vcl/trunk/web/.ht-inc/dashboard.php (added) +++ incubator/vcl/trunk/web/.ht-inc/dashboard.php Wed Oct 20 16:17:19 2010 @@ -0,0 +1,422 @@ +<?php +/* + 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. +*/ + +/** + * \file + */ + +//////////////////////////////////////////////////////////////////////////////// +/// +/// \fn dashboard() +/// +/// \brief +/// +//////////////////////////////////////////////////////////////////////////////// +function dashboard() { + print "<h2>VCL Dashboard</h2>\n"; + print "<table summary=\"\">\n"; + print "<tr>\n"; + + # -------- left column --------- + print "<td valign=\"top\">\n"; + print addWidget('status', 'Current Status'); + print addWidget('topimages', 'Top 5 Images in Use', '(Reservations < 24 hours long)'); + print addWidget('toplongimages', 'Top 5 Long Term Images in Use', '(Reservations > 24 hours long)'); + print addWidget('topfailedcomputers', 'Top Recent Computer Failures', '(Failed in the last 5 days)'); + print "</td>\n"; + # -------- end left column --------- + + # ---------- right column --------- + print "<td valign=\"top\">\n"; + print addWidget('topfailed', 'Top Recent Image Failures', '(Failed in the last 5 days)'); + print addWidget('blockallocation', 'Block Allocation Status'); + print addLineChart('reschart', 'Past 12 Hours of Active Reservations'); + print "</td>\n"; + # -------- end right column -------- + + print "</tr>\n"; + print "</table>\n"; + $cont = addContinuationsEntry('AJupdateDashboard', array('val' => 0), 60, 1, 0); + print "<input type=\"hidden\" id=\"updatecont\" value=\"$cont\">\n"; +} + +//////////////////////////////////////////////////////////////////////////////// +/// +/// \fn +/// +/// \brief +/// +//////////////////////////////////////////////////////////////////////////////// +function AJupdateDashboard() { + $data = array(); + $data['cont'] = addContinuationsEntry('AJupdateDashboard', array(), 60, 1, 0); + $data['status'] = getStatusData(); + $data['topimages'] = getTopImageData(); + $data['toplongimages'] = getTopLongImageData(); + $data['topfailed'] = getTopFailedData(); + $data['topfailedcomputers'] = getTopFailedComputersData(); + $data['reschart'] = getActiveResChartData(); + $data['blockallocation'] = getBlockAllocationData(); + sendJSON($data); +} + +//////////////////////////////////////////////////////////////////////////////// +/// +/// \fn addWidget($id, $title) +/// +/// \param +/// +/// \return +/// +/// \brief +/// +//////////////////////////////////////////////////////////////////////////////// +function addWidget($id, $title, $extra='') { + $txt = "<div class=\"dashwidget\">\n"; + $txt .= "<h3>$title</h3>\n"; + if($extra != '') + $txt .= "<div class=\"extra\">$extra</div>\n"; + $txt .= "<div id=\"$id\"></div>\n"; + $txt .= "</div>\n"; + return $txt; +} + +//////////////////////////////////////////////////////////////////////////////// +/// +/// \fn addLineChart($id) +/// +/// \param +/// +/// \return +/// +/// \brief +/// +//////////////////////////////////////////////////////////////////////////////// +function addLineChart($id, $title) { + $txt = "<div class=\"dashwidget\">\n"; + $txt .= "<h3>$title</h3>\n"; + $txt .= "<div dojoType=\"dojox.charting.widget.Chart2D\" id=\"$id\"\n"; + $txt .= " theme=\"dojox.charting.themes.ThreeD\"\n"; + $txt .= " style=\"width: 300px; height: 300px;\">\n"; + $txt .= "<div class=\"axis\"\n"; + $txt .= " name=\"x\"\n"; + $txt .= " labelFunc=\"timestampToTime\"\n"; + $txt .= " maxLabelSize=\"35\"\n"; + $txt .= " rotation=\"-90\"\n"; + $txt .= " majorTickStep=\"4\"\n"; + $txt .= " minorTickStep=\"1\">\n"; + $txt .= " </div>\n"; + $txt .= "<div class=\"axis\" name=\"y\" vertical=\"true\" includeZero=\"true\"></div>\n"; + $txt .= "<div class=\"plot\" name=\"default\" type=\"Lines\" markers=\"true\"></div>\n"; + $txt .= "<div class=\"plot\" name=\"grid\" type=\"Grid\" vMajorLines=\"false\"></div>\n"; + $txt .= "<div class=\"series\" name=\"Main\" data=\"0\"></div>\n"; + $txt .= "<div class=\"action\" type=\"Tooltip\"></div>\n"; + $txt .= "<div class=\"action\" type=\"Magnify\"></div>\n"; + $txt .= "</div>\n"; + $txt .= "</div>\n"; + return $txt; +} + +//////////////////////////////////////////////////////////////////////////////// +/// +/// \fn getStatusData() +/// +/// \return +/// +/// \brief +/// +//////////////////////////////////////////////////////////////////////////////// +function getStatusData() { + $data = array(); + $data[] = array('key' => 'Active Reservations', 'val' => 0); + $data[] = array('key' => 'Online Computers', 'val' => 0, 'tooltip' => 'Computers in states available, reserved,<br>reloading, inuse, or timeout'); + $data[] = array('key' => 'Failed Computers', 'val' => 0); + $reloadid = getUserlistID('vclrel...@local'); + $query = "SELECT COUNT(id) " + . "FROM request " + . "WHERE userid != $reloadid AND " + . "stateid NOT IN (1, 5, 12) AND " + . "start < NOW() AND " + . "end > NOW()"; + $qh = doQuery($query, 101); + if($row = mysql_fetch_row($qh)) + $data[0]['val'] = $row[0]; + + $query = "SELECT COUNT(id) FROM computer WHERE stateid IN (2, 3, 6, 8, 11)"; + $qh = doQuery($query, 101); + if($row = mysql_fetch_row($qh)) + $data[1]['val'] = $row[0]; + + $query = "SELECT COUNT(id) FROM computer WHERE stateid = 5"; + $qh = doQuery($query, 101); + if($row = mysql_fetch_row($qh)) + $data[2]['val'] = $row[0]; + return $data; +} + +//////////////////////////////////////////////////////////////////////////////// +/// +/// \fn +/// +/// \return +/// +/// \brief +/// +//////////////////////////////////////////////////////////////////////////////// +function getTopImageData() { + $query = "SELECT COUNT(c.currentimageid) AS count, " + . "i.prettyname " + . "FROM computer c, " + . "image i " + . "WHERE c.currentimageid = i.id AND " + . "c.stateid = 8 " + . "GROUP BY c.currentimageid " + . "ORDER BY count DESC " + . "LIMIT 5"; + $query = "SELECT COUNT(rs.imageid) AS count, " + . "i.prettyname " + . "FROM reservation rs, " + . "request rq, " + . "image i " + . "WHERE rs.imageid = i.id AND " + . "rq.stateid = 8 AND " + . "rs.requestid = rq.id AND " + . "TIMESTAMPDIFF(HOUR, rq.start, rq.end) <= 24 " + . "GROUP BY rs.imageid " + . "ORDER BY count DESC " + . "LIMIT 5"; + $data = array(); + $qh = doQuery($query, 101); + while($row = mysql_fetch_assoc($qh)) + $data[] = $row; + return $data; +} + +//////////////////////////////////////////////////////////////////////////////// +/// +/// \fn +/// +/// \return +/// +/// \brief +/// +//////////////////////////////////////////////////////////////////////////////// +function getTopLongImageData() { + $query = "SELECT COUNT(rs.imageid) AS count, " + . "i.prettyname, " + . "TIMESTAMPDIFF(HOUR, rq.start, rq.end) AS reslen " + . "FROM reservation rs, " + . "request rq, " + . "image i " + . "WHERE rs.imageid = i.id AND " + . "rq.stateid = 8 AND " + . "rs.requestid = rq.id " + . "GROUP BY rs.imageid " + . "HAVING reslen > 24 " + . "ORDER BY count DESC " + . "LIMIT 5"; + $query = "SELECT COUNT(rs.imageid) AS count, " + . "i.prettyname " + . "FROM reservation rs, " + . "request rq, " + . "image i " + . "WHERE rs.imageid = i.id AND " + . "rq.stateid = 8 AND " + . "rs.requestid = rq.id AND " + . "TIMESTAMPDIFF(HOUR, rq.start, rq.end) > 24 " + . "GROUP BY rs.imageid " + . "ORDER BY count DESC " + . "LIMIT 5"; + $data = array(); + $qh = doQuery($query, 101); + while($row = mysql_fetch_assoc($qh)) + $data[] = $row; + return $data; +} + +//////////////////////////////////////////////////////////////////////////////// +/// +/// \fn getTopFailedData() +/// +/// \return +/// +/// \brief +/// +//////////////////////////////////////////////////////////////////////////////// +function getTopFailedData() { + $query = "SELECT COUNT(l.imageid) AS count, " + . "i.prettyname " + . "FROM log l, " + . "image i " + . "WHERE l.imageid = i.id AND " + . "l.ending = 'failed' AND " + . "l.start > DATE_SUB(NOW(), INTERVAL 5 DAY) " + . "GROUP BY l.imageid " + . "ORDER BY count DESC " + . "LIMIT 5"; + $data = array(); + $qh = doQuery($query, 101); + while($row = mysql_fetch_assoc($qh)) + $data[] = $row; + return $data; +} + +//////////////////////////////////////////////////////////////////////////////// +/// +/// \fn getTopFailedComputersData() +/// +/// \return +/// +/// \brief +/// +//////////////////////////////////////////////////////////////////////////////// +function getTopFailedComputersData() { + $query = "SELECT COUNT(s.computerid) AS count, " + . "c.hostname " + . "FROM log l, " + . "sublog s, " + . "computer c " + . "WHERE s.logid = l.id AND " + . "s.computerid = c.id AND " + . "l.ending = 'failed' AND " + . "l.start > DATE_SUB(NOW(), INTERVAL 5 DAY) " + . "GROUP BY s.computerid " + . "ORDER BY count DESC " + . "LIMIT 5"; + $data = array(); + $qh = doQuery($query, 101); + while($row = mysql_fetch_assoc($qh)) + $data[] = $row; + return $data; +} + +//////////////////////////////////////////////////////////////////////////////// +/// +/// \fn getActiveResChartData() +/// +/// \return +/// +/// \brief +/// +//////////////////////////////////////////////////////////////////////////////// +function getActiveResChartData() { + $data = array(); + $chartstart = unixFloor15(time() - (12 * 3600)); + $chartend = $chartstart + (12 * 3600) + 900; + for($time = $chartstart, $i = 0; $time < $chartend; $time += 900, $i++) { + $fmttime = date('g:i a', $time); + $data["points"][$i] = array('x' => $i, 'y' => 0, 'value' => $i, 'text' => $fmttime); + } + $data['maxy'] = 0; + $reloadid = getUserlistID('vclrel...@local'); + $query = "SELECT id, " + . "UNIX_TIMESTAMP(start) AS start, " + . "UNIX_TIMESTAMP(finalend) AS end " + . "FROM log " + . "WHERE start < NOW() AND " + . "finalend > DATE_SUB(NOW(), INTERVAL 12 HOUR) AND " + . "ending NOT IN ('failed', 'failedtest') AND " + . "wasavailable = 1 AND " + . "userid != $reloadid"; + $qh = doQuery($query, 101); + while($row = mysql_fetch_assoc($qh)) { + for($binstart = $chartstart, $binend = $chartstart + 900, $binindex = 0; + $binend <= $chartend; + $binstart += 900, $binend += 900, $binindex++) { + if($binend <= $row['start']) + continue; + elseif($row['start'] < $binend && + $row['end'] > $binstart) { + $data["points"][$binindex]['y']++; + } + elseif($binstart >= $row['end']) + break; + } + } + for($time = $chartstart, $i = 0; $time < $chartend; $time += 900, $i++) { + if($data["points"][$i]['y'] > $data['maxy']) + $data['maxy'] = $data['points'][$i]['y']; + $data["points"][$i]['tooltip'] = "{$data['points'][$i]['text']}: {$data['points'][$i]['y']}"; + } + return $data; +} + +//////////////////////////////////////////////////////////////////////////////// +/// +/// \fn getBlockAllocationData() +/// +/// \param +/// +/// \return +/// +/// \brief +/// +//////////////////////////////////////////////////////////////////////////////// +function getBlockAllocationData() { + # active block allocation + $query = "SELECT COUNT(id) " + . "FROM blockTimes " + . "WHERE skip = 0 AND " + . "start < NOW() AND " + . "end > NOW()"; + $qh = doQuery($query, 101); + $row = mysql_fetch_row($qh); + $blockcount = $row[0]; + # computers in blockComputers for active allocations + $query = "SELECT bc.computerid, " + . "c.stateid " + . "FROM blockComputers bc " + . "LEFT JOIN computer c ON (c.id = bc.computerid) " + . "LEFT JOIN blockTimes bt ON (bt.id = bc.blockTimeid) " + . "WHERE c.stateid IN (2, 3, 6, 8, 19) AND " + . "bt.start < NOW() AND " + . "bt.end > NOW()"; + $qh = doQuery($query, 101); + $total = 0; + $used = 0; + while($row = mysql_fetch_assoc($qh)) { + $total++; + if($row['stateid'] == 3 || $row['stateid'] == 8) + $used++; + } + if($total) + $compused = sprintf('%d / %d (%0.2f %%)', $used, $total, ($used / $total * 100)); + else + $compused = 0; + # number of computers that should be allocated + $query = "SELECT br.numMachines " + . "FROM blockRequest br " + . "LEFT JOIN blockTimes bt ON (bt.blockRequestid = br.id) " + . "WHERE bt.start < NOW() AND " + . "bt.end > NOW() AND " + . "bt.skip = 0"; + $alloc = 0; + $qh = doQuery($query, 101); + while($row = mysql_fetch_assoc($qh)) + $alloc += $row['numMachines']; + if($alloc) + $failed = sprintf('%d / %d (%0.2f %%)', ($alloc - $total), $alloc, (($alloc - $total) / $alloc * 100)); + else + $failed = 0; + $data = array(); + $data[] = array('title' => 'Active Block Allocations', 'val' => $blockcount); + $data[] = array('title' => 'Block Computer Usage', 'val' => $compused); + $data[] = array('title' => 'Failed Block Computers', 'val' => $failed); + return $data; +} +?> Modified: incubator/vcl/trunk/web/.ht-inc/states.php URL: http://svn.apache.org/viewvc/incubator/vcl/trunk/web/.ht-inc/states.php?rev=1025626&r1=1025625&r2=1025626&view=diff ============================================================================== --- incubator/vcl/trunk/web/.ht-inc/states.php (original) +++ incubator/vcl/trunk/web/.ht-inc/states.php Wed Oct 20 16:17:19 2010 @@ -55,6 +55,7 @@ $actions["entry"] = array('main', 'continuationsError', 'requestBlockAllocation', 'siteMaintenance', + 'dashboard', ); $noHTMLwrappers = array('sendRDPfile', @@ -142,6 +143,8 @@ $noHTMLwrappers = array('sendRDPfile', 'AJgetScheduleTimesData', 'AJsaveScheduleTimes', 'AJvalidateUserid', + 'AJupdateDashboard', + 'AJgetStatData', ); # main @@ -555,19 +558,12 @@ $actions['pages']['userLookup'] = "userL $actions['pages']['submitUserLookup'] = "userLookup"; # statistics -# TODO might need the statgraph modes to be entry modes $actions['mode']['selectstats'] = "selectStatistics"; # entry $actions['mode']['viewstats'] = "viewStatistics"; -$actions['mode']['statgraphday'] = "sendStatGraphDay"; -$actions['mode']['statgraphhour'] = "sendStatGraphHour"; -$actions['mode']['statgraphdayconcuruser'] = "sendStatGraphDayConUsers"; -$actions['mode']['statgraphdayconcurblade'] = "sendStatGraphConBladeUser"; +$actions['mode']['AJgetStatData'] = "AJgetStatData"; $actions['pages']['selectstats'] = "statistics"; $actions['pages']['viewstats'] = "statistics"; -$actions['pages']['statgraphday'] = "statistics"; -$actions['pages']['statgraphhour'] = "statistics"; -$actions['pages']['statgraphdayconcuruser'] = "statistics"; -$actions['pages']['statgraphdayconcurblade'] = "statistics"; +$actions['pages']['AJgetStatData'] = "statistics"; # help $actions['mode']['helpform'] = "printHelpForm"; # entry @@ -635,6 +631,12 @@ $actions['pages']['AJgetDelSiteMaintenan $actions['pages']['AJeditSiteMaintenance'] = "sitemaintenance"; $actions['pages']['AJdeleteSiteMaintenance'] = "sitemaintenance"; +# dashboard +$actions['mode']['dashboard'] = "dashboard"; +$actions['mode']['AJupdateDashboard'] = "AJupdateDashboard"; +$actions['pages']['dashboard'] = "dashboard"; +$actions['pages']['AJupdateDashboard'] = "dashboard"; + # RPC $actions['mode']['xmlrpccall'] = "xmlrpccall"; $actions['mode']['xmlrpcaffiliations'] = "xmlrpcgetaffiliations"; Modified: incubator/vcl/trunk/web/.ht-inc/statistics.php URL: http://svn.apache.org/viewvc/incubator/vcl/trunk/web/.ht-inc/statistics.php?rev=1025626&r1=1025625&r2=1025626&view=diff ============================================================================== --- incubator/vcl/trunk/web/.ht-inc/statistics.php (original) +++ incubator/vcl/trunk/web/.ht-inc/statistics.php Wed Oct 20 16:17:19 2010 @@ -16,21 +16,6 @@ limitations under the License. */ -if($phpVer == 5) { - if(is_dir(".ht-inc/jpgraph")) { - require_once(".ht-inc/jpgraph/jpgraph.php"); - require_once(".ht-inc/jpgraph/jpgraph_bar.php"); - require_once(".ht-inc/jpgraph/jpgraph_line.php"); - } -} -else { - if(is_dir(".ht-inc/jpgraph.old")) { - require_once(".ht-inc/jpgraph.old/jpgraph.php"); - require_once(".ht-inc/jpgraph.old/jpgraph_bar.php"); - require_once(".ht-inc/jpgraph.old/jpgraph_line.php"); - } -} - /** * \file */ @@ -289,6 +274,8 @@ function viewStatistics() { # lengths $length = $row["finalend"] - $row["start"]; + if($length < 0) + $length = 0; if($length <= 1800) $lengths["30min"]++; elseif($length <= 3600) @@ -467,6 +454,7 @@ function viewStatistics() { print " </TR>\n"; print "</TABLE>\n"; print "<br>\n"; + print "</div>\n"; $unixstart = datetimeToUnix($start); $unixend = datetimeToUnix($end); @@ -476,30 +464,38 @@ function viewStatistics() { 'end' => $end, 'affilid' => $affilid); print "<H2>Reservations by Day</H2>\n"; - $cont = addContinuationsEntry('statgraphday', $cdata); - print "<img src=" . BASEURL . SCRIPT . "?continuation=$cont>"; + print "<small>(Reservations with start time on given day)</small><br>\n"; + $cdata['divid'] = 'resbyday'; + $cont = addContinuationsEntry('AJgetStatData', $cdata); + print "<input type=hidden id=statdaycont value=\"$cont\">\n"; + print "<div id=\"resbyday\" style=\"width: 400px; height: 310px;\">(Loading...)</div>\n"; print "<H2>Max Concurrent Reservations By Day</H2>\n"; if($unixend - $unixstart > SECINMONTH) print "(this graph only available for up to a month of data)<br>\n"; else { - $cont = addContinuationsEntry('statgraphdayconcuruser', $cdata); - print "<img src=" . BASEURL . SCRIPT . "?continuation=$cont>"; + $cdata['divid'] = 'maxconcurresday'; + $cont = addContinuationsEntry('AJgetStatData', $cdata); + print "<input type=hidden id=statconcurrescont value=\"$cont\">\n"; + print "<div id=\"maxconcurresday\" style=\"width: 400px; height: 310px;\">Loading graph data...</div>\n"; } print "<H2>Max Concurrent Blade Reservations By Day</H2>\n"; if($unixend - $unixstart > SECINMONTH) print "(this graph only available for up to a month of data)<br>\n"; else { - $cont = addContinuationsEntry('statgraphdayconcurblade', $cdata); - print "<img src=" . BASEURL . SCRIPT . "?continuation=$cont>"; + $cdata['divid'] = 'maxconcurbladeday'; + $cont = addContinuationsEntry('AJgetStatData', $cdata); + print "<input type=hidden id=statconcurbladecont value=\"$cont\">\n"; + print "<div id=\"maxconcurbladeday\" style=\"width: 400px; height: 310px;\">Loading graph data...</div>\n"; } print "<H2>Reservations by Hour</H2>\n"; - print "(Averaged over the time period)<br><br>\n"; - $cont = addContinuationsEntry('statgraphhour', $cdata); - print "<img src=" . BASEURL . SCRIPT . "?continuation=$cont>"; - print "</div>\n"; + print "<small>(Active reservations during given hour averaged over selected dates)</small><br><br>\n"; + $cdata['divid'] = 'resbyhour'; + $cont = addContinuationsEntry('AJgetStatData', $cdata); + print "<input type=hidden id=statreshourcont value=\"$cont\">\n"; + print "<div id=\"resbyhour\" style=\"width: 400px; height: 310px;\">Loading graph data...</div>\n"; $endtime = microtime(1); $end = $endtime - $timestart; @@ -508,36 +504,26 @@ function viewStatistics() { //////////////////////////////////////////////////////////////////////////////// /// -/// \fn sendStatGraphDay() +/// \fn AJgetStatData() /// -/// \brief sends a graph image +/// \brief gets statistical data for a dojox chart and returns it in json format /// //////////////////////////////////////////////////////////////////////////////// -function sendStatGraphDay() { - global $xaxislabels, $inContinuation; - if(! $inContinuation) - return; +function AJgetStatData() { $start = getContinuationVar("start"); $end = getContinuationVar("end"); $affilid = getContinuationVar("affilid"); - $graphdata = getStatGraphDayData($start, $end, $affilid); - $count = count($graphdata["labels"]); - if($count < 8) - $labelinterval = 1; - else - $labelinterval = $count / 7; - $xaxislabels = $graphdata["labels"]; - $graph = new Graph(300, 300, "auto"); - $graph->SetScale("textlin"); - $plot = new BarPlot($graphdata["points"]); - $graph->Add($plot); - $graph->xaxis->SetLabelFormatCallback('statXaxisDayCallback'); - $graph->xaxis->SetLabelAngle(90); - $graph->xaxis->SetTextLabelInterval($labelinterval); - $graph->yaxis->SetTitle('Reservations with start time on given day', - 'high'); - $graph->SetMargin(40,40,20,80); - $graph->Stroke(); + $divid = getContinuationVar('divid'); + if($divid == 'resbyday') + $data = getStatGraphDayData($start, $end, $affilid); + elseif($divid == 'maxconcurresday') + $data = getStatGraphDayConUsersData($start, $end, $affilid); + elseif($divid == 'maxconcurbladeday') + $data = getStatGraphConBladeUserData($start, $end, $affilid); + elseif($divid == 'resbyhour') + $data = getStatGraphHourData($start, $end, $affilid); + $data['id'] = $divid; + sendJSON($data); } //////////////////////////////////////////////////////////////////////////////// @@ -548,9 +534,13 @@ function sendStatGraphDay() { /// \param $end - ending day in YYYY-MM-DD format /// \param $affilid - affiliationid of data to gather /// -/// \return an array whose keys are the days (in YYYY-MM-DD format) between -/// $start and $end, inclusive, and whose values are the number of reservations -/// on each day +/// \return an array with three keys:\n +/// \b points - an array with y and tooltip keys that have the same value which +/// is the y value at that point\n +/// \b xlabels - an array with value and text keys, value's value is just an +/// increasing integer starting from 1, text's value is the label +/// to display on the x axis for the poing\n +/// \b maxy - the max y value of the data /// /// \brief queries the log table to get reservations between $start and $end /// and creates an array with the number of reservations on each day @@ -562,10 +552,12 @@ function getStatGraphDayData($start, $en $data = array(); $data["points"] = array(); - $data["labels"] = array(); + $data['xlabels'] = array(); + $data['maxy'] = 0; $reloadid = getUserlistID('vclrel...@local'); + $cnt = 0; for($i = $startunix; $i < $endunix; $i += SECINDAY) { - array_push($data["labels"], date('Y-m-d', $i)); + $cnt++; $startdt = unixToDatetime($i); $enddt = unixToDatetime($i + SECINDAY); if($affilid != 0) { @@ -589,69 +581,35 @@ function getStatGraphDayData($start, $en } $qh = doQuery($query, 295); if($row = mysql_fetch_row($qh)) - array_push($data["points"], $row[0]); + $value = $row[0]; else - array_push($data["points"], 0); + $value = 0; + $label = date('m/d/Y', $i); + $data['points'][] = array('y' => (int)$value, 'tooltip' => "$label: " . (int)$value); + if($value > $data['maxy']) + $data['maxy'] = (int)$value; + $data['xlabels'][] = array('value' => $cnt, 'text' => $label); } return($data); } //////////////////////////////////////////////////////////////////////////////// /// -/// \fn statXaxisDayCallback($val) -/// -/// \param $val - value passed in by SetLabelFormatCallback -/// -/// \return day of week -/// -/// \brief formats $val into day of week -/// -//////////////////////////////////////////////////////////////////////////////// -function statXaxisDayCallback($val) { - global $xaxislabels; - if(array_key_exists((int)$val, $xaxislabels)) { - return date('n/d/Y', datetimeToUnix($xaxislabels[$val] . " 00:00:00")) . " "; - } - else { - return $val; - } -} - -//////////////////////////////////////////////////////////////////////////////// -/// -/// \fn sendStatGraphHour() -/// -/// \brief sends a graph image -/// -//////////////////////////////////////////////////////////////////////////////// -function sendStatGraphHour() { - global $xaxislabels, $inContinuation; - if(! $inContinuation) - return; - $start = getContinuationVar("start"); - $end = getContinuationVar("end"); - $affilid = getContinuationVar("affilid"); - $graphdata = getStatGraphHourData($start, $end, $affilid); - $graph = new Graph(300, 300, "auto"); - $graph->SetScale("textlin"); - $plot = new LinePlot($graphdata["points"]); - $graph->Add($plot); - $graph->xaxis->SetLabelFormatCallback('statXaxisHourCallback'); - $graph->xaxis->SetLabelAngle(90); - $graph->xaxis->SetTextLabelInterval(2); - $graph->yaxis->SetTitle('Active reservations during given hour', 'high'); - $graph->SetMargin(40,40,20,80); - $graph->Stroke(); -} - -//////////////////////////////////////////////////////////////////////////////// -/// /// \fn getStatGraphHourData($start, $end, $affilid) /// /// \param $start - starting day in YYYY-MM-DD format /// \param $end - ending day in YYYY-MM-DD format /// \param $affilid - affiliationid of data to gather /// +/// \return an array with two keys:\n +/// \b points - an array with 5 keys:\n +/// \t x - increasing integer starting from 1\n +/// \t y - y value for the point\n +/// \t value - same as x\n +/// \t text - label for x axis for the point\n +/// \t tooltip - tooltip to be displayed when point is hovered\n +/// \b maxy - the max y value of the data +/// /// \return an array whose keys are the days (in YYYY-MM-DD format) between /// $start and $end, inclusive, and whose values are the number of reservations /// on each day @@ -671,8 +629,9 @@ function getStatGraphHourData($start, $e $data = array(); $data["points"] = array(); for($i = 0; $i < 24; $i++) { - $data["points"][$i] = 0; + $data["points"][$i] = array('x' => $i, 'y' => 0, 'value' => $i, 'text' => statHourFormatX($i), 'tooltip' => 0); } + $data["maxy"] = 0; $reloadid = getUserlistID('vclrel...@local'); if($affilid != 0) { @@ -701,7 +660,6 @@ function getStatGraphHourData($start, $e . "l.wasavailable = 1"; } $qh = doQuery($query, 296); - $count = 0; while($row = mysql_fetch_assoc($qh)) { $startmin = ($row['shour'] * 60) + $row['smin']; $endmin = ($row['ehour'] * 60) + $row['emin']; @@ -713,7 +671,7 @@ function getStatGraphHourData($start, $e continue; elseif($startmin < $binend && $endmin > $binstart) { - $data["points"][$binindex]++; + $data["points"][$binindex]['y']++; } elseif($binstart >= $endmin) break; @@ -721,70 +679,39 @@ function getStatGraphHourData($start, $e } # comment this to change graph to be aggregate instead of average - foreach($data["points"] as $key => $val) - $data["points"][$key] = $val / $days; + foreach($data["points"] as $key => $val) { + $newval = $val['y'] / $days; + if($newval - (int)$newval != 0) + $newval = sprintf('%.2f', $newval); + $data['points'][$key]['y'] = $newval; + $data['points'][$key]['tooltip'] = $newval; + if($newval > $data['maxy']) + $data['maxy'] = $newval; + } return($data); } //////////////////////////////////////////////////////////////////////////////// /// -/// \fn statXaxisHourCallback($val) +/// \fn statHourFormatX($val) /// -/// \param $val - value passed in by SetLabelFormatCallback +/// \param $val - hour of day (0-23) /// /// \return day of week /// -/// \brief formats $val into day of week +/// \brief formats $val into "hour am/pm" /// //////////////////////////////////////////////////////////////////////////////// -function statXaxisHourCallback($val) { - if($val == 0) { +function statHourFormatX($val) { + if($val == 0) return "12 am "; - } - elseif($val < 12) { + elseif($val < 12) return "$val am "; - } - elseif($val == 12) { + elseif($val == 12) return "$val pm "; - } - else { - return $val - 12 . " pm "; - } -} - -//////////////////////////////////////////////////////////////////////////////// -/// -/// \fn sendStatGraphDayConUsers() -/// -/// \brief sends a graph image -/// -//////////////////////////////////////////////////////////////////////////////// -function sendStatGraphDayConUsers() { - global $xaxislabels, $inContinuation; - if(! $inContinuation) - return; - $start = getContinuationVar("start"); - $end = getContinuationVar("end"); - $affilid = getContinuationVar("affilid"); - $graphdata = getStatGraphDayConUsersData($start, $end, $affilid); - $count = count($graphdata["labels"]); - if($count < 8) - $labelinterval = 1; else - $labelinterval = $count / 7; - $xaxislabels = $graphdata["labels"]; - $graph = new Graph(300, 300, "auto"); - $graph->SetScale("textlin"); - $plot = new BarPlot($graphdata["points"]); - $graph->Add($plot); - $graph->xaxis->SetLabelFormatCallback('statXaxisDayConUsersCallback'); - $graph->xaxis->SetLabelAngle(90); - $graph->xaxis->SetTextLabelInterval($labelinterval); - $graph->yaxis->SetTitle('Maximum concurrent reservations per day', - 'high'); - $graph->SetMargin(40,40,20,80); - $graph->Stroke(); + return $val - 12 . " pm "; } //////////////////////////////////////////////////////////////////////////////// @@ -795,9 +722,13 @@ function sendStatGraphDayConUsers() { /// \param $end - ending day in YYYY-MM-DD format /// \param $affilid - affiliationid of data to gather /// -/// \return an array whose keys are the days (in YYYY-MM-DD format) between -/// $start and $end, inclusive, and whose values are the max concurrent users -/// on each day +/// \return an array with three keys:\n +/// \b points - an array with y and tooltip keys that have the same value which +/// is the y value at that point\n +/// \b xlabels - an array with value and text keys, value's value is just an +/// increasing integer starting from 1, text's value is the label +/// to display on the x axis for the poing\n +/// \b maxy - the max y value of the data /// /// \brief queries the log table to get reservations between $start and $end /// and creates an array with the max concurrent users per day @@ -812,16 +743,17 @@ function getStatGraphDayConUsersData($st $data = array(); $data["points"] = array(); - $data["labels"] = array(); + $data["xlabels"] = array(); + $data["maxy"] = 0; $reloadid = getUserlistID('vclrel...@local'); + $cnt = 0; for($daystart = $startunix; $daystart < $endunix; $daystart += SECINDAY) { - array_push($data["labels"], date('Y-m-d', $daystart)); + $cnt++; $count = array(); for($j = 0; $j < 24; $j++) { $count[$j] = 0; } - $startdt = unixToDatetime($daystart); $enddt = unixToDatetime($daystart + SECINDAY); if($affilid != 0) { @@ -863,77 +795,30 @@ function getStatGraphDayConUsersData($st } } rsort($count); - array_push($data["points"], $count[0]); + $label = date('m/d/Y', $daystart); + $data["points"][] = array('y' => $count[0], 'tooltip' => "$label: {$count[0]}"); + if($count[0] > $data['maxy']) + $data['maxy'] = $count[0]; + $data['xlabels'][] = array('value' => $cnt, 'text' => $label); } return($data); } //////////////////////////////////////////////////////////////////////////////// /// -/// \fn statXaxisDayConUsersCallback($val) -/// -/// \param $val - value passed in by SetLabelFormatCallback -/// -/// \return day of week -/// -/// \brief formats $val into day of week -/// -//////////////////////////////////////////////////////////////////////////////// -function statXaxisDayConUsersCallback($val) { - global $xaxislabels; - if(array_key_exists((int)$val, $xaxislabels)) { - return date('n/d/Y', datetimeToUnix($xaxislabels[$val] . " 00:00:00")) . " "; - } - else { - return $val; - } -} - -//////////////////////////////////////////////////////////////////////////////// -/// -/// \fn sendStatGraphConBladeUser() -/// -/// \brief sends a graph image of max concurrent users of blades per day -/// -//////////////////////////////////////////////////////////////////////////////// -function sendStatGraphConBladeUser() { - global $xaxislabels, $inContinuation; - if(! $inContinuation) - return; - $start = getContinuationVar("start"); - $end = getContinuationVar("end"); - $affilid = getContinuationVar("affilid"); - $graphdata = getStatGraphConBladeUserData($start, $end, $affilid); - $count = count($graphdata["labels"]); - if($count < 8) - $labelinterval = 1; - else - $labelinterval = $count / 7; - $xaxislabels = $graphdata["labels"]; - $graph = new Graph(300, 300, "auto"); - $graph->SetScale("textlin"); - $plot = new BarPlot($graphdata["points"]); - $graph->Add($plot); - $graph->xaxis->SetLabelFormatCallback('statXaxisDayConUsersCallback'); - $graph->xaxis->SetLabelAngle(90); - $graph->xaxis->SetTextLabelInterval($labelinterval); - $graph->yaxis->SetTitle('Maximum concurrent reservations per day', - 'high'); - $graph->SetMargin(40,40,20,80); - $graph->Stroke(); -} - -//////////////////////////////////////////////////////////////////////////////// -/// /// \fn getStatGraphConBladeUserData($start, $end, $affilid) /// /// \param $start - starting day in YYYY-MM-DD format /// \param $end - ending day in YYYY-MM-DD format /// \param $affilid - affiliationid of data to gather /// -/// \return an array whose keys are the days (in YYYY-MM-DD format) between -/// $start and $end, inclusive, and whose values are the max concurrent users -/// of blades on each day +/// \return an array with three keys:\n +/// \b points - an array with y and tooltip keys that have the same value which +/// is the y value at that point\n +/// \b xlabels - an array with value and text keys, value's value is just an +/// increasing integer starting from 1, text's value is the label +/// to display on the x axis for the poing\n +/// \b maxy - the max y value of the data /// /// \brief queries the log table to get reservations between $start and $end /// and creates an array with the max concurrent users of blades per day @@ -948,11 +833,13 @@ function getStatGraphConBladeUserData($s $data = array(); $data["points"] = array(); - $data["labels"] = array(); + $data["xlabels"] = array(); + $data["maxy"] = 0; $reloadid = getUserlistID('vclrel...@local'); + $cnt = 0; for($daystart = $startunix; $daystart < $endunix; $daystart += SECINDAY) { - array_push($data["labels"], date('Y-m-d', $daystart)); + $cnt++; $count = array(); for($j = 0; $j < 24; $j++) { $count[$j] = 0; @@ -1010,29 +897,12 @@ function getStatGraphConBladeUserData($s } } rsort($count); - array_push($data["points"], $count[0]); + $label = date('m/d/Y', $daystart); + $data["points"][] = array('y' => $count[0], 'tooltip' => "$label: {$count[0]}"); + if($count[0] > $data['maxy']) + $data['maxy'] = $count[0]; + $data['xlabels'][] = array('value' => $cnt, 'text' => $label); } return($data); } - -//////////////////////////////////////////////////////////////////////////////// -/// -/// \fn statXaxisConBladeUserCallback($val) -/// -/// \param $val - value passed in by SetLabelFormatCallback -/// -/// \return day of week -/// -/// \brief formats $val into day of week -/// -//////////////////////////////////////////////////////////////////////////////// -function statXaxisConBladeUserCallback($val) { - global $xaxislabels; - if(array_key_exists((int)$val, $xaxislabels)) { - return date('n/d/Y', datetimeToUnix($xaxislabels[$val] . " 00:00:00")) . " "; - } - else { - return $val; - } -} ?> Modified: incubator/vcl/trunk/web/.ht-inc/utils.php URL: http://svn.apache.org/viewvc/incubator/vcl/trunk/web/.ht-inc/utils.php?rev=1025626&r1=1025625&r2=1025626&view=diff ============================================================================== --- incubator/vcl/trunk/web/.ht-inc/utils.php (original) +++ incubator/vcl/trunk/web/.ht-inc/utils.php Wed Oct 20 16:17:19 2010 @@ -307,6 +307,9 @@ function initGlobals() { case 'vm': require_once(".ht-inc/vm.php"); break; + case 'dashboard': + require_once(".ht-inc/dashboard.php"); + break; default: require_once(".ht-inc/requests.php"); } @@ -8776,14 +8779,10 @@ function getNavMenu($inclogout, $inchome $rt .= menulistLI('statistics'); $rt .= "<a href=\"" . BASEURL . SCRIPT . "?mode=selectstats\">"; $rt .= "Statistics</a></li>\n"; - if($skin != 'ecu') { - $rt .= menulistLI('help'); - $rt .= "<a href=\"" . HELPURL . "\">Help</a></li>\n"; - } - if($skin == 'ecu') { - $rt .= "<li><a href=\"http://www.ecu.edu/cs-itcs/vcl/connect.cfm\">Requirements</a></li>\n"; - $rt .= "<li><a href=\"http://www.ecu.edu/cs-itcs/vcl/save.cfm\">File Saving</a></li>\n"; - $rt .= "<li><a href=\"http://www.ecu.edu/cs-itcs/vcl/faqs.cfm\">Help</a></li>\n"; + if($viewmode == ADMIN_DEVELOPER) { + $rt .= menulistLI('dashboard'); + $rt .= "<a href=\"" . BASEURL . SCRIPT . "?mode=dashboard\">"; + $rt .= "Dashboard</a></li>\n"; } if(in_array("userGrant", $user["privileges"]) || in_array("resourceGrant", $user["privileges"]) || @@ -8989,6 +8988,21 @@ function getDojoHTML($refresh) { 'dijit.Tooltip', 'dijit.Dialog'); break; + case 'viewstats': + $dojoRequires = array('dojo.parser', + 'dojox.charting.Chart2D', + 'dojox.charting.action2d.Tooltip', + 'dojox.charting.action2d.Magnify', + 'dojox.charting.themes.ThreeD'); + break; + case 'dashboard': + $dojoRequires = array('dojo.parser', + 'dijit.Tooltip', + 'dojox.charting.widget.Chart2D', + 'dojox.charting.action2d.Tooltip', + 'dojox.charting.action2d.Magnify', + 'dojox.charting.themes.ThreeD'); + break; } if(empty($dojoRequires)) return ''; @@ -9313,6 +9327,39 @@ function getDojoHTML($refresh) { $rt .= " });\n"; $rt .= "</script>\n"; return $rt; + case "viewstats": + $rt .= "<style type=\"text/css\">\n"; + $rt .= " @import \"themes/$skin/css/dojo/$skin.css\";\n"; + $rt .= "</style>\n"; + $rt .= "<script type=\"text/javascript\" src=\"js/statistics.js\"></script>\n"; + $rt .= "<script type=\"text/javascript\" src=\"dojo/dojo/dojo.js\"\n"; + $rt .= " djConfig=\"parseOnLoad: true\">\n"; + $rt .= "</script>\n"; + $rt .= "<script type=\"text/javascript\">\n"; + $rt .= " dojo.addOnLoad(function() {\n"; + foreach($dojoRequires as $req) + $rt .= " dojo.require(\"$req\");\n"; + $rt .= " generateGraphs();\n"; + $rt .= " });\n"; + $rt .= "</script>\n"; + return $rt; + case "dashboard": + $rt .= "<style type=\"text/css\">\n"; + $rt .= " @import \"themes/$skin/css/dojo/$skin.css\";\n"; + $rt .= " @import \"css/dashboard.css\";\n"; + $rt .= "</style>\n"; + $rt .= "<script type=\"text/javascript\" src=\"js/dashboard.js\"></script>\n"; + $rt .= "<script type=\"text/javascript\" src=\"dojo/dojo/dojo.js\"\n"; + $rt .= " djConfig=\"parseOnLoad: true, debug: true\">\n"; + $rt .= "</script>\n"; + $rt .= "<script type=\"text/javascript\">\n"; + $rt .= " dojo.addOnLoad(function() {\n"; + foreach($dojoRequires as $req) + $rt .= " dojo.require(\"$req\");\n"; + $rt .= " updateDashboard();\n"; + $rt .= " });\n"; + $rt .= "</script>\n"; + return $rt; default: $rt .= "<style type=\"text/css\">\n"; Added: incubator/vcl/trunk/web/css/dashboard.css URL: http://svn.apache.org/viewvc/incubator/vcl/trunk/web/css/dashboard.css?rev=1025626&view=auto ============================================================================== --- incubator/vcl/trunk/web/css/dashboard.css (added) +++ incubator/vcl/trunk/web/css/dashboard.css Wed Oct 20 16:17:19 2010 @@ -0,0 +1,23 @@ +.dashwidget { + border: 1px solid; + text-align: center; + /*border-radius: 10px; + -moz-border-radius: 10px;*/ + margin-bottom: 8px; +} + +.dashwidget .extra { + margin-bottom: 5px; +} + +.dashwidget table { + margin-left: auto; + margin-right: auto; +} + +.dashwidget h3 { + background: #0053fb; + color: white; + margin-top: 0px; + margin-bottom: 2px; +} Modified: incubator/vcl/trunk/web/js/code.js URL: http://svn.apache.org/viewvc/incubator/vcl/trunk/web/js/code.js?rev=1025626&r1=1025625&r2=1025626&view=diff ============================================================================== --- incubator/vcl/trunk/web/js/code.js (original) +++ incubator/vcl/trunk/web/js/code.js Wed Oct 20 16:17:19 2010 @@ -123,10 +123,10 @@ var genericCB = function(type, data, evt eval(data); } -var errorHandler = function(type, error, data) { - if(args.dojoType == 'cancel') +var errorHandler = function(error, ioArgs) { + if(error.name == 'cancel') return; - alert('error occurred' + error.message + data.responseText); + alert('AJAX Error: ' + error.message + '\nLine ' + error.lineNumber + ' in ' + error.fileName); } function errorHandler(data, ioArgs) { Added: incubator/vcl/trunk/web/js/dashboard.js URL: http://svn.apache.org/viewvc/incubator/vcl/trunk/web/js/dashboard.js?rev=1025626&view=auto ============================================================================== --- incubator/vcl/trunk/web/js/dashboard.js (added) +++ incubator/vcl/trunk/web/js/dashboard.js Wed Oct 20 16:17:19 2010 @@ -0,0 +1,204 @@ +/* +* 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. +*/ + +function RPCwrapper(data, CB, dojson) { + if(dojson) { + dojo.xhrPost({ + url: 'index.php', + load: CB, + handleAs: "json", + error: errorHandler, + content: data, + timeout: 15000 + }); + } + else { + dojo.xhrPost({ + url: 'index.php', + load: CB, + error: errorHandler, + content: data, + timeout: 15000 + }); + } +} + +function generalReqCB(data, ioArgs) { + eval(data); + document.body.style.cursor = 'default'; +} + +function updateDashboard() { + var cont = dojo.byId('updatecont').value; + RPCwrapper({continuation: cont}, updateDashboardCB, 1); +} + +function updateDashboardCB(data, ioArgs) { + dojo.byId('updatecont').value = data.items.cont; + updateStatus(data.items.status); + updateTopImages(data.items.topimages); + updateTopLongImages(data.items.toplongimages); + updateTopFailed(data.items.topfailed); + updateTopFailedComputers(data.items.topfailedcomputers); + updateResChart(data.items.reschart); + updateBlockAllocation(data.items.blockallocation); + setTimeout(updateDashboard, 15000); +} + +function updateStatus(data) { + var obj = dojo.byId('status'); + var txt = '<table>'; + for(var i = 0; i < data.length; i++) { + txt += '<tr><th align="right">' + if(data[i].tooltip) { + txt += '<span id="status' + i + '">' + + data[i].key + + '</span>' + + '</th><td>' + + data[i].val + + '</td></tr>'; + } + else { + txt += data[i].key + + '</th><td>' + + data[i].val + + '</td></tr>'; + } + } + txt += '</table>'; + obj.innerHTML = txt; + for(var i = 0; i < data.length; i++) { + if(data[i].tooltip) { + var tt = new dijit.Tooltip({ + connectId: ['status' + i], + label: data[i].tooltip + }); + } + } +} + +function updateTopImages(data) { + var obj = dojo.byId('topimages'); + if(data.length == 0) { + obj.innerHTML = 'No recent reservations'; + return; + } + var txt = '<table>'; + for(var i = 0; i < data.length; i++) { + txt += '<tr><th align="right">' + + data[i].prettyname + + '</th><td>' + + data[i].count + + '</td></tr>'; + } + txt += '</table>'; + obj.innerHTML = txt; +} + +function updateTopLongImages(data) { + var obj = dojo.byId('toplongimages'); + if(data.length == 0) { + obj.innerHTML = 'No recent reservations'; + return; + } + var txt = '<table>'; + for(var i = 0; i < data.length; i++) { + txt += '<tr><th align="right">' + + data[i].prettyname + + '</th><td>' + + data[i].count + + '</td></tr>'; + } + txt += '</table>'; + obj.innerHTML = txt; +} + +function updateTopFailed(data) { + var obj = dojo.byId('topfailed'); + if(data.length == 0) { + obj.innerHTML = 'No recent reservations'; + return; + } + var txt = '<table>'; + for(var i = 0; i < data.length; i++) { + txt += '<tr><th align="right">' + + data[i].prettyname + + '</th><td>' + + data[i].count + + '</td></tr>'; + } + txt += '</table>'; + obj.innerHTML = txt; +} + +function updateTopFailedComputers(data) { + var obj = dojo.byId('topfailedcomputers'); + if(data.length == 0) { + obj.innerHTML = 'No recent reservations'; + return; + } + var txt = '<table>'; + for(var i = 0; i < data.length; i++) { + txt += '<tr><th align="right">' + + data[i].hostname + + '</th><td>' + + data[i].count + + '</td></tr>'; + } + txt += '</table>'; + obj.innerHTML = txt; +} + +function updateBlockAllocation(data) { + var obj = dojo.byId('blockallocation'); + var txt = '<table>'; + for(var i = 0; i < data.length; i++) { + txt += '<tr><th align="right">' + + data[i].title + + '</th><td>' + + data[i].val + + '</td></tr>'; + } + txt += '</table>'; + obj.innerHTML = txt; +} + +function updateResChart(data) { + var graph = dijit.byId('reschart').chart; + graph.updateSeries('Main', data.points); + graph.labeldata = data.points; + graph.render(); +} + +function timestampToTime(val) { + if(! dijit.byId('reschart').chart.labeldata) + return ''; + else + var data = dijit.byId('reschart').chart.labeldata; + return data[val]['text']; + var d = new Date(); + d.setTime(val*1000); + var h = d.getHours(); + if(h == 0) + return "12:" + d.getMinutes() + " am"; + else if(h < 12) + return h + ":" + d.getMinutes() + " am"; + else if(h == 12) + return "12:" + d.getMinutes() + " pm"; + else + return (h - 12) + ":" + d.getMinutes() + "pm"; +} Added: incubator/vcl/trunk/web/js/statistics.js URL: http://svn.apache.org/viewvc/incubator/vcl/trunk/web/js/statistics.js?rev=1025626&view=auto ============================================================================== --- incubator/vcl/trunk/web/js/statistics.js (added) +++ incubator/vcl/trunk/web/js/statistics.js Wed Oct 20 16:17:19 2010 @@ -0,0 +1,144 @@ +/* +* 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. +*/ + +function RPCwrapper(data, CB, dojson) { + if(dojson) { + dojo.xhrPost({ + url: 'index.php', + load: CB, + handleAs: "json", + error: errorHandler, + content: data, + timeout: 300000 + }); + } + else { + dojo.xhrPost({ + url: 'index.php', + load: CB, + error: errorHandler, + content: data, + timeout: 300000 + }); + } +} + +function generalReqCB(data, ioArgs) { + eval(data); + document.body.style.cursor = 'default'; +} + +function generateGraphs() { + var cont = dojo.byId('statdaycont').value; + RPCwrapper({continuation: cont}, generateColGraphsCB, 1); + var cont = dojo.byId('statreshourcont').value; + RPCwrapper({continuation: cont}, generateHourGraphsCB, 1); + if(dojo.byId('statconcurrescont')) { + var cont = dojo.byId('statconcurrescont').value; + RPCwrapper({continuation: cont}, generateColGraphsCB, 1); + } + if(dojo.byId('statconcurbladecont')) { + var cont = dojo.byId('statconcurbladecont').value; + RPCwrapper({continuation: cont}, generateColGraphsCB, 1); + } +} + +function generateColGraphsCB(data, ioArgs) { + dojo.byId(data.items.id).innerHTML = ''; + var graph = new dojox.charting.Chart2D(data.items.id); + if(data.items.maxy <= 400) + var majortick = 50; + else if(data.items.maxy <= 600) + var majortick = 100; + else if(data.items.maxy <= 1000) + var majortick = 200; + else { + var majortick = data.items.maxy / 10; + majortick = (majortick - (majortick % 200)) || 200; + } + graph.setTheme(dojox.charting.themes.ThreeD); + if(data.items.points.length < 10) + var gap = 6; + else if(data.items.points.length < 20) + var gap = 3; + else if(data.items.points.length < 50) + var gap = 2; + else + var gap = 0; + var xtickstep = parseInt(data.items.xlabels.length / 10) || 1; + graph.addAxis("x", { + includeZero: false, + labels: data.items.xlabels, + rotation: -90, + minorTicks: false, + font: 'normal normal normal 11px verdana', + majorTickStep: xtickstep + }); + graph.addAxis('y', { + vertical: true, + fixUpper: "major", + includeZero: true, + minorTicks: true, + minorLabels: false, + majorTickStep: majortick, + minorTickStep: majortick / 2, + }); + graph.addPlot('default', {type: "Columns", gap: gap}); + graph.addPlot('Grid', {type: 'Grid', hMajorLines: true, vMajorLines: false}); + graph.addSeries("Main", data.items.points, {stroke: {width: 1}}); + var a = new dojox.charting.action2d.Tooltip(graph); + graph.render(); +} + +function generateHourGraphsCB(data, ioArgs) { + dojo.byId(data.items.id).innerHTML = ''; + var graph = new dojox.charting.Chart2D(data.items.id); + if(data.items.maxy <= 50) + var majortick = 5; + else if(data.items.maxy <= 100) + var majortick = 10; + else if(data.items.maxy <= 200) + var majortick = 20; + else { + var majortick = data.items.maxy / 10; + majortick = (majortick - (majortick % 100)) || 100; + } + graph.setTheme(dojox.charting.themes.ThreeD); + graph.addAxis("x", { + includeZero: true, + labels: data.items.points, + rotation: -90, + minorTicks: false, + font: 'normal normal normal 11px verdana', + majorTickStep: 2 + }); + graph.addAxis('y', { + vertical: true, + fixUpper: "major", + includeZero: true, + minorTicks: true, + minorLabels: false, + majorTickStep: majortick, + minorTickStep: majortick / 5, + }); + graph.addPlot('default', {markers: true}); + graph.addPlot('Grid', {type: 'Grid', hMajorLines: true, vMajorLines: false}); + graph.addSeries("Main", data.items.points); + var a = new dojox.charting.action2d.Tooltip(graph); + var a = new dojox.charting.action2d.Magnify(graph); + graph.render(); +}