accumulo-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ctubb...@apache.org
Subject [12/54] [abbrv] accumulo git commit: ACCUMULO-2181/3005 Porting Monitor
Date Thu, 06 Jul 2017 20:43:06 GMT
http://git-wip-us.apache.org/repos/asf/accumulo/blob/0ca5cd33/server/monitor/src/main/resources/resources/functions.js
----------------------------------------------------------------------
diff --git a/server/monitor/src/main/resources/resources/functions.js b/server/monitor/src/main/resources/resources/functions.js
new file mode 100644
index 0000000..d09c2fe
--- /dev/null
+++ b/server/monitor/src/main/resources/resources/functions.js
@@ -0,0 +1,686 @@
+/*
+* 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.
+*/
+
+// Suffixes for quantity
+var QUANTITY_SUFFIX = ['', 'K', 'M', 'B', 'T', 'e15', 'e18', 'e21'];
+// Suffixes for size
+var SIZE_SUFFIX = ['', 'K', 'M', 'G', 'T', 'P', 'E', 'Z'];
+
+/**
+ * Initializes Auto Refresh to false if it is not set,
+ * and creates listeners for auto refresh
+ */
+function setupAutoRefresh() {
+  // Sets auto refresh to true or false
+  if (!sessionStorage.autoRefresh) {
+    sessionStorage.autoRefresh = 'false';
+  }
+  // Need this to set the initial value for the autorefresh on page load
+  if (sessionStorage.autoRefresh == 'false') {
+    $('.auto-refresh').parent().removeClass('active');
+  } else {
+    $('.auto-refresh').parent().addClass('active');
+  }
+  // Initializes the auto refresh on click listener
+  $('.auto-refresh').click(function(e) {
+    if ($(this).parent().attr('class') == 'active') {
+      $(this).parent().removeClass('active');
+      sessionStorage.autoRefresh = 'false';
+    } else {
+      $(this).parent().addClass('active');
+      sessionStorage.autoRefresh = 'true';
+    }
+  });
+}
+
+/**
+ * Global timer that checks for auto refresh status every 5 seconds
+ */
+TIMER = setInterval(function() {
+  if (sessionStorage.autoRefresh == 'true') {
+    $('.auto-refresh').parent().addClass('active');
+    refresh();
+    refreshNavBar();
+  } else {
+    $('.auto-refresh').parent().removeClass('active');
+  }
+}, 5000);
+
+/**
+ * Empty function in case there is no refresh implementation
+ */
+function refresh() {
+}
+
+/**
+ * Converts a number to a size with suffix
+ *
+ * @param {number} size Number to convert
+ * @return {string} Number with suffix added
+ */
+function bigNumberForSize(size) {
+  if (size === null)
+    size = 0;
+  return bigNumber(size, SIZE_SUFFIX, 1024);
+}
+
+/**
+ * Converts a number to a quantity with suffix
+ *
+ * @param {number} quantity Number to convert
+ * @return {string} Number with suffix added
+ */
+function bigNumberForQuantity(quantity) {
+  if (quantity === null)
+    quantity = 0;
+  return bigNumber(quantity, QUANTITY_SUFFIX, 1000);
+}
+
+/**
+ * Adds the suffix to the number, converts the number to one close to the base
+ *
+ * @param {number} big Number to convert
+ * @param {array} suffixes Suffixes to use for convertion
+ * @param {number} base Base to use for convertion
+ * @return {string} The new value with the suffix
+ */
+function bigNumber(big, suffixes, base) {
+  // If the number is smaller than the base, return thee number with no suffix
+  if (big < base) {
+    return big + suffixes[0];
+  }
+  // Finds which suffix to use
+  var exp = Math.floor(Math.log(big) / Math.log(base));
+  // Divides the bumber by the equivalent suffix number
+  var val = big / Math.pow(base, exp);
+  // Keeps the number to 2 decimal places and adds the suffix
+  return val.toFixed(2) + suffixes[exp];
+}
+
+/**
+ * Converts the time to short number and adds unit
+ *
+ * @param {number} time Time in microseconds
+ * @return {string} The time with units
+ */
+function timeDuration(time) {
+  var ms, sec, min, hr, day, yr;
+  ms = sec = min = hr = day = yr = -1;
+
+  time = Math.floor(time);
+
+  // If time is 0 return a dash
+  if (time == 0) {
+    return '&mdash;';
+  }
+
+  // Obtains the milliseconds, if time is 0, return milliseconds, and units
+  ms = time % 1000;
+  time = Math.floor(time / 1000);
+  if (time == 0) {
+    return ms + 'ms';
+  }
+
+  // Obtains the seconds, if time is 0, return seconds, milliseconds, and units
+  sec = time % 60;
+  time = Math.floor(time / 60);
+  if (time == 0) {
+    return sec + 's' + '&nbsp;' + ms + 'ms';
+  }
+
+  // Obtains the minutes, if time is 0, return minutes, seconds, and units
+  min = time % 60;
+  time = Math.floor(time / 60);
+  if (time == 0) {
+    return min + 'm' + '&nbsp;' + sec + 's';
+  }
+
+  // Obtains the hours, if time is 0, return hours, minutes, and units
+  hr = time % 24;
+  time = Math.floor(time / 24);
+  if (time == 0) {
+    return hr + 'h' + '&nbsp;' + min + 'm';
+  }
+
+  // Obtains the days, if time is 0, return days, hours, and units
+  day = time % 365;
+  time = Math.floor(time / 365);
+  if (time == 0) {
+    return day + 'd' + '&nbsp;' + hr + 'h';
+  }
+
+  // Obtains the years, if time is 0, return years, days, and units
+  yr = Math.floor(time);
+  return yr + 'y' + '&nbsp;' + day + 'd';
+}
+
+/**
+ * Sorts the selected table by column in the direction chosen
+ *
+ * @param {string} tableID Table to sort
+ * @param {string} direction Direction to sort table, asc or desc
+ * @param {number} n Column to sort
+ */
+function sortTables(tableID, direction, n) {
+  var table, rows, switching, i, x, y, h, shouldSwitch, dir, xFinal, yFinal;
+  table = document.getElementById(tableID);
+  switching = true;
+
+  dir = direction;
+  sessionStorage.direction = dir;
+
+  // Select the rows of the table
+  rows = table.getElementsByTagName('tr');
+
+  // Clears the sortable class from the table columns
+  var count = 0;
+  while (rows[0].getElementsByTagName('th').length > count) {
+    var tmpH = rows[0].getElementsByTagName('th')[count];
+    tmpH.classList.remove('sortable');
+    if (rows.length > 2) {
+      tmpH.classList.add('sortable');
+    }
+    $(tmpH.getElementsByTagName('span')).remove();
+    count += 1;
+  }
+
+  // If there are more than 2 rows, add arrow to the selected column
+  if (rows.length <= 2) {
+      switching = false;
+  } else {
+    h = rows[0].getElementsByTagName('th')[n];
+    if (dir == 'asc') {
+      $(h).append('<span class="glyphicon glyphicon-chevron-up"' +
+          ' width="10px" height="10px" />');
+    } else if (dir == 'desc') {
+      $(h).append('<span class="glyphicon glyphicon-chevron-down"' +
+          ' width="10px" height="10px" />');
+    }
+  }
+
+  /*
+   * Make a loop that will continue until
+   * no switching has been done:
+   */
+  while (switching) {
+    switching = false;
+    rows = table.getElementsByTagName('tr');
+
+    /*
+     * Loop through all table rows (except the
+     * first, which contains table headers):
+     */
+    for (i = 1; i < (rows.length - 1); i++) {
+      shouldSwitch = false;
+      /*
+       * Get two elements to compare,
+       * one from current row and one from the next:
+       * If the element is a dash, convert to null, otherwise,
+       * if it is a string, convert to number
+       */
+      x = rows[i].getElementsByTagName('td')[n].getAttribute('data-value');
+      xFinal = (x === '-' || x === '&mdash;' ?
+          null : (Number(x) == x ? Number(x) : x));
+
+      y = rows[i + 1].getElementsByTagName('td')[n].getAttribute('data-value');
+      yFinal = (y === '-' || y === '&mdash;' ?
+          null : (Number(y) == y ? Number(y) : y));
+
+      /*
+       * Check if the two rows should switch place,
+       * based on the direction, asc or desc:
+       */
+      if (dir == 'asc') {
+        if (xFinal > yFinal || (xFinal !== null && yFinal === null)) {
+          // if so, mark as a switch and break the loop:
+          shouldSwitch = true;
+          break;
+        }
+      } else if (dir == 'desc') {
+        if (xFinal < yFinal || (yFinal !== null && xFinal === null)) {
+          // if so, mark as a switch and break the loop:
+          shouldSwitch = true;
+          break;
+        }
+      }
+    }
+    if (shouldSwitch) {
+      /*
+       * If a switch has been marked, make the switch
+       * and mark that a switch has been done:
+       */
+      rows[i].parentNode.insertBefore(rows[i + 1], rows[i]);
+      switching = true;
+    }
+  }
+}
+
+/**
+ * Clears the selected table while leaving the headers
+ *
+ * @param {string} tableID Table to clear
+ */
+function clearTable(tableID) {
+  // JQuery selector to select all rows except for the first row (header)
+  $('#' + tableID).find('tr:not(:first)').remove();
+}
+
+///// REST Calls /////////////
+
+/**
+ * REST GET call for the master information,
+ * stores it on a sessionStorage variable
+ */
+function getMaster() {
+  $.getJSON('/rest/master', function(data) {
+    sessionStorage.master = JSON.stringify(data);
+  });
+}
+
+/**
+ * REST GET call for the zookeeper information,
+ * stores it on a sessionStorage variable
+ */
+function getZK() {
+  $.getJSON('/rest/zk', function(data) {
+    sessionStorage.zk = JSON.stringify(data);
+  });
+}
+
+/**
+ * REST GET call for the namespaces, stores it on a global variable
+ */
+function getNamespaces() {
+  $.getJSON('/rest/tables/namespaces', function(data) {
+    NAMESPACES = JSON.stringify(data);
+  });
+}
+
+/**
+ * REST GET call for the tables on each namespace,
+ * stores it on a sessionStorage variable
+ *
+ * @param {array} namespaces Array holding the selected namespaces
+ */
+function getNamespaceTables(namespaces) {
+
+  // Creates a JSON object to store the tables
+  var jsonObj = {};
+  jsonObj.tables = [];
+
+  /* If the namespace array include *, get all tables, otherwise,
+   * get tables from specific namespaces
+   */
+  if (namespaces.indexOf('*') != -1) {
+    getTables();
+  } else {
+    $.each(namespaces, function(key, val) {
+      /* Makes the rest call for each of the namespaces in the array,
+       * stores them on the JSON object
+       */
+      if (val !== '*') {
+        var call = '/rest/tables/namespace/' + val;
+        $.getJSON(call, function(data) {
+          $.each(data.tables, function(key2, val2) {
+            jsonObj.tables.push(val2);
+          });
+        });
+      }
+    });
+    sessionStorage.tables = JSON.stringify(jsonObj);
+  }
+}
+
+/**
+ * REST GET call for the tables, stores it on a sessionStorage variable
+ */
+function getTables() {
+  $.getJSON('/rest/tables', function(data) {
+    sessionStorage.tables = JSON.stringify(data);
+  });
+}
+
+/**
+ * REST POST call to clear a specific dead server
+ *
+ * @param {string} server Dead Server ID
+ */
+function clearDeadServers(server) {
+  var call = '/rest/tservers?server=' + server;
+  $.post(call);
+}
+
+/**
+ * REST GET call for the tservers, stores it on a sessionStorage variable
+ */
+function getTServers() {
+  $.getJSON('/rest/tservers', function(data) {
+    sessionStorage.tservers = JSON.stringify(data);
+  });
+}
+
+/**
+ * REST GET call for the tservers, stores it on a sessionStorage variable
+ *
+ * @param {string} server Server ID
+ */
+function getTServer(server) {
+  var call = '/rest/tservers/' + server;
+  $.getJSON(call, function(data) {
+    sessionStorage.server = JSON.stringify(data);
+  });
+}
+
+/**
+ * REST GET call for the scans, stores it on a sessionStorage variable
+ */
+function getScans() {
+  $.getJSON('/rest/scans', function(data) {
+    sessionStorage.scans = JSON.stringify(data);
+  });
+}
+
+/**
+ * REST GET call for the bulk imports, stores it on a sessionStorage variable
+ */
+function getBulkImports() {
+  $.getJSON('/rest/bulkImports', function(data) {
+    sessionStorage.bulkImports = JSON.stringify(data);
+  });
+}
+
+/**
+ * REST GET call for the garbage collector,
+ * stores it on a sessionStorage variable
+ */
+function getGarbageCollector() {
+  $.getJSON('/rest/gc', function(data) {
+    sessionStorage.gc = JSON.stringify(data);
+  });
+}
+
+/**
+ * REST GET call for the server stats, stores it on a sessionStorage variable
+ */
+function getServerStats() {
+  $.getJSON('/rest/tservers/serverStats', function(data) {
+    sessionStorage.serverStats = JSON.stringify(data);
+  });
+}
+
+/**
+ * REST GET call for the recovery list, stores it on a sessionStorage variable
+ */
+function getRecoveryList() {
+  $.getJSON('/rest/tservers/recovery', function(data) {
+    sessionStorage.recoveryList = JSON.stringify(data);
+  });
+}
+
+/**
+ * REST GET call for the participating tablet servers,
+ * stores it on a sessionStorage variable
+ *
+ * @param {string} table Table ID
+ */
+function getTableServers(table) {
+  var call = '/rest/tables/' + table;
+  $.getJSON(call, function(data) {
+    sessionStorage.tableServers = JSON.stringify(data);
+  });
+}
+
+/**
+ * REST GET call for the trace summary, stores it on a sessionStorage variable
+ *
+ * @param {string} minutes Number of minutes to display trace summary
+ */
+function getTraceSummary(minutes) {
+  var call = '/rest/trace/summary/' + minutes;
+  $.getJSON(call, function(data) {
+    sessionStorage.traceSummary = JSON.stringify(data);
+  });
+}
+
+/**
+ * REST GET call for the trace type, stores it on a sessionStorage variable
+ *
+ * @param {string} type Type of the trace
+ * @param {string} minutes Number of minutes to display trace
+ */
+function getTraceOfType(type, minutes) {
+  var call = '/rest/trace/listType/' + type + '/' + minutes;
+  $.getJSON(call, function(data) {
+    sessionStorage.traceType = JSON.stringify(data);
+  });
+}
+
+/**
+ * REST GET call for the trace id, stores it on a sessionStorage variable
+ *
+ * @param {string} id Trace ID
+ */
+function getTraceShow(id) {
+  var call = '/rest/trace/show/' + id;
+  $.getJSON(call, function(data) {
+    sessionStorage.traceShow = JSON.stringify(data);
+  });
+}
+
+/**
+ * REST GET call for the logs, stores it on a sessionStorage variable
+ */
+function getLogs() {
+  $.getJSON('/rest/logs', function(data) {
+    sessionStorage.logs = JSON.stringify(data);
+  });
+}
+
+/**
+ * REST POST call to clear logs
+ */
+function clearLogs() {
+  $.post('/rest/logs');
+}
+
+/**
+ * REST GET call for the problems
+ */
+function getProblems() {
+  getProblemSummary();
+  getProblemDetails();
+}
+
+/**
+ * REST POST call to clear all table problems
+ *
+ * @param {string} tableID Table ID
+ */
+function clearTableProblems(tableID) {
+  var call = '/rest/problems/summary?s=' + tableID;
+  // Change plus sign to use ASCII value to send it as a URL query parameter
+  call = call.split('+').join('%2B');
+  $.post(call);
+}
+
+/**
+ * REST POST call to clear detail problems
+ *
+ * @param {string} table Table ID
+ * @param {string} resource Resource for problem
+ * @param {string} type Type of problem
+ */
+function clearDetailsProblems(table, resource, type) {
+  var call = '/rest/problems/details?table=' + table + '&resource=' +
+   resource + '&ptype=' + type;
+  // Changes plus sign to use ASCII value to send it as a URL query parameter
+  call = call.split('+').join('%2B');
+  $.post(call);
+}
+
+/**
+ * REST GET call for the problems summary,
+ * stores it on a sessionStorage variable
+ */
+function getProblemSummary() {
+  $.getJSON('/rest/problems/summary', function(data) {
+    sessionStorage.problemSummary = JSON.stringify(data);
+  });
+}
+
+/**
+ * REST GET call for the problems details,
+ * stores it on a sessionStorage variable
+ */
+function getProblemDetails() {
+  $.getJSON('/rest/problems/details', function(data) {
+    sessionStorage.problemDetails = JSON.stringify(data);
+  });
+}
+
+/**
+ * REST GET call for the replication table,
+ * stores it on a sessionStorage variable
+ */
+function getReplication() {
+  $.getJSON('/rest/replication', function(data) {
+    sessionStorage.replication = JSON.stringify(data);
+  });
+}
+
+/**
+ * Creates a banner
+ *
+ * @param {string} id Banner ID
+ * @param {string} bannerClass Class for the banner
+ * @param {string} text Text to display on the banner
+ */
+function doBanner(id, bannerClass, text) {
+  $('<div/>', {
+   html: text,
+   class: 'alert alert-' + bannerClass,
+   role: 'alert'
+  }).appendTo('#' + id);
+}
+
+//// Overview Plots Rest Calls
+
+/**
+ * REST GET call for the ingest rate,
+ * stores it on a sessionStorage variable
+ */
+function getIngestRate() {
+  $.getJSON('/rest/statistics/time/ingestRate', function(data) {
+    sessionStorage.ingestRate = JSON.stringify(data);
+  });
+}
+
+/**
+ * REST GET call for the scan entries,
+ * stores it on a sessionStorage variable
+ */
+function getScanEntries() {
+  $.getJSON('/rest/statistics/time/scanEntries', function(data) {
+    sessionStorage.scanEntries = JSON.stringify(data);
+  });
+}
+
+/**
+ * REST GET call for the ingest byte rate,
+ * stores it on a sessionStorage variable
+ */
+function getIngestByteRate() {
+  $.getJSON('/rest/statistics/time/ingestByteRate', function(data) {
+    sessionStorage.ingestMB = JSON.stringify(data);
+  });
+}
+
+/**
+ * REST GET call for the query byte rate, stores it on a sessionStorage variable
+ */
+function getQueryByteRate() {
+  $.getJSON('/rest/statistics/time/queryByteRate', function(data) {
+    sessionStorage.queryMB = JSON.stringify(data);
+  });
+}
+
+/**
+ * REST GET call for the load average, stores it on a sessionStorage variable
+ */
+function getLoadAverage() {
+  $.getJSON('/rest/statistics/time/load', function(data) {
+    sessionStorage.loadAvg = JSON.stringify(data);
+  });
+}
+
+/**
+ * REST GET call for the lookups, stores it on a sessionStorage variable
+ */
+function getLookups() {
+  $.getJSON('/rest/statistics/time/lookups', function(data) {
+    sessionStorage.lookups = JSON.stringify(data);
+  });
+}
+
+/**
+ * REST GET call for the minor compactions,
+ * stores it on a sessionStorage variable
+ */
+function getMinorCompactions() {
+  $.getJSON('/rest/statistics/time/minorCompactions', function(data) {
+    sessionStorage.minorCompactions = JSON.stringify(data);
+  });
+}
+
+/**
+ * REST GET call for the major compactions,
+ * stores it on a sessionStorage variable
+ */
+function getMajorCompactions() {
+  $.getJSON('/rest/statistics/time/majorCompactions', function(data) {
+    sessionStorage.majorCompactions = JSON.stringify(data);
+  });
+}
+
+/**
+ * REST GET call for the index cache hit rate,
+ * stores it on a sessionStorage variable
+ */
+function getIndexCacheHitRate() {
+  $.getJSON('/rest/statistics/time/indexCacheHitRate', function(data) {
+    sessionStorage.indexCache = JSON.stringify(data);
+  });
+}
+
+/**
+ * REST GET call for the data cache hit rate,
+ * stores it on a sessionStorage variable
+ */
+function getDataCacheHitRate() {
+  $.getJSON('/rest/statistics/time/dataCacheHitRate', function(data) {
+    sessionStorage.dataCache = JSON.stringify(data);
+  });
+}
+
+/**
+ * REST GET call for the server status, stores it on a sessionStorage variable
+ */
+function getStatus() {
+  $.getJSON('/rest/status', function(data) {
+    sessionStorage.status = JSON.stringify(data);
+  });
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/0ca5cd33/server/monitor/src/main/resources/resources/gc.js
----------------------------------------------------------------------
diff --git a/server/monitor/src/main/resources/resources/gc.js b/server/monitor/src/main/resources/resources/gc.js
new file mode 100644
index 0000000..a57907f
--- /dev/null
+++ b/server/monitor/src/main/resources/resources/gc.js
@@ -0,0 +1,278 @@
+/*
+* 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.
+*/
+
+/**
+ * Creates garbage collector initial table
+ */
+$(document).ready(function() {
+  createHeader();
+  doBanner('gcBanner', 'danger', 'Collector is Unavailable');
+  refreshGC();
+});
+
+/**
+ * Makes the REST calls, generates the tables with the new information
+ */
+function refreshGC() {
+  $.ajaxSetup({
+    async: false
+  });
+  getGarbageCollector();
+  $.ajaxSetup({
+    async: true
+  });
+  refreshGCTable();
+}
+
+/**
+ * Used to redraw the page
+ */
+function refresh() {
+  refreshGC();
+}
+
+/**
+ * Generates the garbage collector table
+ */
+function refreshGCTable() {
+  // Checks the status of the garbage collector
+  var status = JSON.parse(sessionStorage.status).gcStatus;
+
+  // Hides the banner, removes any rows from the table and hides the table
+  $('#gcBanner').hide();
+  $('#gcActivity tr:gt(0)').remove();
+  $('#gcActivity').hide();
+
+  /* Check if the status of the gc is an error, if so, show banner, otherwise,
+   * create the table
+   */
+  if (status === 'ERROR') {
+    $('#gcBanner').show();
+  } else {
+    $('#gcActivity').show();
+    var data = JSON.parse(sessionStorage.gc);
+
+    // Checks if there is a collection activity
+    if (data.files.lastCycle.finished <= 0 &&
+        data.files.currentCycle.started <= 0 &&
+        data.wals.lastCycle.finished <= 0 &&
+        data.wals.currentCycle.started <= 0) {
+      var item = '<td class="center" colspan="7"><i>No Collection Activity' +
+          '</i></td>';
+
+      $('<tr/>', {
+        html: item
+      }).appendTo('#gcActivity');
+    } else {
+
+      // File Collection Last Cycle row
+      if (data.files.lastCycle.finished > 0) {
+        var items = [];
+
+        var working = data.files.lastCycle;
+
+        items.push('<td class="firstcell left" data-value="File Collection' +
+            ' Last Cycle">File&nbsp;Collection,&nbsp;Last&nbsp;Cycle</td>"');
+
+        var date = new Date(working.finished);
+        items.push('<td class="right" data-value="' + working.finished +
+            '">' + date.toLocaleString() + '</td>');
+
+        items.push('<td class="right" data-value="' + working.candidates +
+            '">' + bigNumberForQuantity(working.candidates) + '</td>');
+
+        items.push('<td class="right" data-value="' + working.deleted +
+            '">' + bigNumberForQuantity(working.deleted) + '</td>');
+
+        items.push('<td class="right" data-value="' + working.inUse +
+            '">' + bigNumberForQuantity(working.inUse) + '</td>');
+
+        items.push('<td class="right" data-value="' + working.errors +
+            '">' + bigNumberForQuantity(working.errors) + '</td>');
+
+        items.push('<td class="right" data-value="' +
+            (working.finished - working.started) + '">' +
+            timeDuration(working.finished - working.started) + '</td>');
+
+        $('<tr/>', {
+          html: items.join('')
+        }).appendTo('#gcActivity');
+      }
+
+      // File Collection Running row
+      if (data.files.currentCycle.started > 0) {
+        var items = [];
+
+        var working = data.files.currentCycle;
+
+        items.push('<td class="firstcell left" data-value="File Collection' +
+            ' Running">File&nbsp;Collection,&nbsp;Running</td>');
+
+        var date = new Date(working.finished);
+        items.push('<td class="right" data-value="' + working.finished +
+            '">' + date.toLocaleString() + '</td>');
+
+        items.push('<td class="right" data-value="' + working.candidates +
+            '">' + bigNumberForQuantity(working.candidates) + '</td>');
+
+        items.push('<td class="right" data-value="' + working.deleted +
+            '">' + bigNumberForQuantity(working.deleted) + '</td>');
+
+        items.push('<td class="right" data-value="' + working.inUse +
+            '">' + bigNumberForQuantity(working.inUse) + '</td>');
+
+        items.push('<td class="right" data-value="' + working.errors +
+            '">' + bigNumberForQuantity(working.errors) + '</td>');
+
+        items.push('<td class="right" data-value="' +
+            (working.finished - working.started) + '">' +
+            timeDuration(working.finished - working.started) + '</td>');
+
+        $('<tr/>', {
+          html: items.join('')
+        }).appendTo('#gcActivity');
+      }
+
+      // WAL Collection Last Cycle row
+      if (data.wals.lastCycle.finished > 0) {
+        var items = [];
+
+        var working = data.wals.lastCycle;
+
+        items.push('<td class="firstcell left" data-value="WAL Collection' +
+            ' Last Cycle">WAL&nbsp;Collection,&nbsp;Last&nbsp;Cycle</td>');
+
+        var date = new Date(working.finished);
+        items.push('<td class="right" data-value="' + working.finished +
+            '">' + date.toLocaleString() + '</td>');
+
+        items.push('<td class="right" data-value="' + working.candidates +
+            '">' + bigNumberForQuantity(working.candidates) + '</td>');
+
+        items.push('<td class="right" data-value="' + working.deleted +
+            '">' + bigNumberForQuantity(working.deleted) + '</td>');
+
+        items.push('<td class="right" data-value="' + working.inUse +
+            '">' + bigNumberForQuantity(working.inUse) + '</td>');
+
+        items.push('<td class="right" data-value="' + working.errors +
+            '">' + bigNumberForQuantity(working.errors) + '</td>');
+
+        items.push('<td class="right" data-value="' +
+            (working.finished - working.started) + '">' +
+            timeDuration(working.finished - working.started) + '</td>');
+
+        $('<tr/>', {
+          html: items.join('')
+        }).appendTo('#gcActivity');
+      }
+
+      // WAL Collection Running row
+      if (data.wals.currentCycle.started > 0) {
+        var items = [];
+
+        var working = data.wals.currentCycle;
+
+        items.push('<td class="firstcell left" data-value="WAL Collection' +
+            ' Running">WAL&nbsp;Collection,&nbsp;Running</td>');
+
+        var date = new Date(working.finished);
+        items.push('<td class="right" data-value="' + working.finished +
+            '">' + date.toLocaleString() + '</td>');
+
+        items.push('<td class="right" data-value="' + working.candidates +
+            '">' + bigNumberForQuantity(working.candidates) + '</td>');
+
+        items.push('<td class="right" data-value="' + working.deleted +
+            '">' + bigNumberForQuantity(working.deleted) + '</td>');
+
+        items.push('<td class="right" data-value="' + working.inUse +
+            '">' + bigNumberForQuantity(working.inUse) + '</td>');
+
+        items.push('<td class="right" data-value="' + working.errors +
+            '">' + bigNumberForQuantity(working.errors) + '</td>');
+
+        items.push('<td class="right" data-value="' +
+            (working.finished - working.started) + '">' +
+            timeDuration(working.finished - working.started) + '</td>');
+
+        $('<tr/>', {
+          html: items.join('')
+        }).appendTo('#gcActivity');
+      }
+    }
+  }
+}
+
+/**
+ * Sorts the garbage collector table on the selected column
+ *
+ * @param {number} n Column number to sort by
+ */
+function sortTable(n) {
+
+  if (sessionStorage.tableColumnSort !== undefined &&
+      sessionStorage.tableColumnSort == n &&
+      sessionStorage.direction !== undefined) {
+    direction = sessionStorage.direction === 'asc' ? 'desc' : 'asc';
+  } else {
+    direction = sessionStorage.direction === undefined ?
+        'asc' : sessionStorage.direction;
+  }
+  sessionStorage.tableColumnSort = n;
+  sortTables('gcActivity', direction, n);
+}
+
+/**
+ * Create tooltip for table column information
+ */
+$(function() {
+  $(document).tooltip();
+});
+
+/**
+ * Creates the garbage collector header
+ */
+function createHeader() {
+  var caption = [];
+
+  caption.push('<span class="table-caption">Collection&nbsp;' +
+      'Activity</span><br />');
+
+  $('<caption/>', {
+    html: caption.join('')
+  }).appendTo('#gcActivity');
+
+  var items = [];
+
+  /*
+   * Adds the columns, add sortTable function on click,
+   * if the column has a description, add title taken from the global.js
+   */
+  items.push('<th class="firstcell" onclick="sortTable(0)">Activity' +
+      '&nbsp;</th>');
+  items.push('<th onclick="sortTable(1)">Finished&nbsp;</th>');
+  items.push('<th onclick="sortTable(2)">Candidates&nbsp;</th>');
+  items.push('<th onclick="sortTable(3)">Deleted&nbsp;</th>');
+  items.push('<th onclick="sortTable(4)">In&nbsp;Use&nbsp;</th>');
+  items.push('<th onclick="sortTable(5)">Errors&nbsp;</th>');
+  items.push('<th onclick="sortTable(6)">Duration&nbsp;</th>');
+
+  $('<tr/>', {
+    html: items.join('')
+  }).appendTo('#gcActivity');
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/0ca5cd33/server/monitor/src/main/resources/resources/global.js
----------------------------------------------------------------------
diff --git a/server/monitor/src/main/resources/resources/global.js b/server/monitor/src/main/resources/resources/global.js
new file mode 100644
index 0000000..d31cd1a
--- /dev/null
+++ b/server/monitor/src/main/resources/resources/global.js
@@ -0,0 +1,96 @@
+/*
+* 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.
+*/
+
+/**
+ * Descriptions used for table columns
+ */
+var descriptions = {
+  '# Tablets' : 'Tables are broken down into ranges of rows called tablets.',
+  '# Offline Tablets' : 'Tablets unavailable for query or ingest. May be a' +
+      ' transient condition when tablets are moved for balancing.',
+  'Entries' : 'Key/value pairs over each instance, table or tablet.',
+  'Entries in Memory' : 'The total number of key/value pairs stored in' +
+      ' memory and not yet written to disk.',
+  'Ingest' : 'The number of Key/Value pairs inserted. (Note that deletes' +
+      ' are "inserted")',
+  'Entries Read' : 'The number of Key/Value pairs read on the server side.' +
+      'Not all key values read may be returned to client because of filtering.',
+  'Entries Returned' : 'The number of Key/Value pairs returned to clients' +
+      'during queries. This is not the number of scans.',
+  'Hold Time' : 'The amount of time that ingest operations are suspended' +
+      ' while waiting for data to be written to disk.',
+  'Running Scans' : 'Information about the scans threads. Shows how many' +
+      ' threads are running and how much work is queued for the threads.',
+  'Minor Compactions' : 'Flushing memory to disk is called a "Minor' +
+      ' Compaction." Multiple tablets can be minor compacted simultaneously,' +
+      ' but sometimes they must wait for resources to be available.' +
+      ' These tablets that are waiting for compaction are "queued"' +
+      ' and are indicated using parentheses. So 2 (3) indicates there' +
+      ' are two compactions running and three queued waiting for resources.',
+  'Major Compactions' : 'Gathering up many small files and rewriting them' +
+      ' as one larger file is called a "Major Compaction". Major Compactions' +
+      ' are performed as a consequence of new files created from Minor' +
+      ' Compactions and Bulk Load operations. They reduce the number of' +
+      ' files used during queries.',
+  'Master' : 'The hostname of the master server',
+  '# Online Tablet Servers' : 'Number of tablet servers currently available',
+  '# Total Tablet Servers' : 'The total number of tablet servers configured',
+  'Last GC' : 'The last time files were cleaned-up from HDFS.',
+  'Total Entries' : 'The total number of key/value pairs in Accumulo',
+  'Total Ingest' : 'The number of Key/Value pairs inserted, per second.' +
+      ' Note that deleted records are "inserted" and will make the ingest' +
+      ' rate increase in the near-term.',
+  'Total Entries Read' : 'The total number of Key/Value pairs read on the' +
+      ' server side.  Not all may be returned because of filtering.',
+  'Total Entries Returned' : 'The total number of Key/Value pairs returned' +
+      ' as a result of scans.',
+  'Max Hold Time' : 'The maximum amount of time that ingest has been held' +
+      ' across all servers due to a lack of memory to store the records',
+  'OS Load' : 'The Unix one minute load average. The average number of' +
+      ' processes in the run queue over a one minute interval.',
+  'Query' : 'The number of key/value pairs returned to clients.' +
+      ' (Not the number of scans)',
+  'Index Cache Hit Rate' : 'The recent index cache hit rate.',
+  'Data Cache Hit Rate' : 'The recent data cache hit rate.',
+  '# Scans' : 'Number of scans presently running',
+  'Oldest Scan' : 'The age of the oldest scan on this server.',
+  'Import Age' : 'The age of the import.',
+  'Import State' : 'The current state of the bulk import',
+  '# Imports' : 'Number of imports presently running',
+  'Oldest Age' : 'The age of the oldest import running on this server.',
+  'Trace Start' : 'Start Time of selected trace type',
+  'Span Time' : 'Span Time of selected trace type',
+  'Source' : 'Service and Location of selected trace type',
+  'Trace Type' : 'Trace Type',
+  'Total Spans' : 'Number of spans of this type',
+  'Short Span' : 'Shortest span duration',
+  'Long Span' : 'Longest span duration',
+  'Avg Span' : 'Average span duration',
+  'Histogram' : 'Counts of spans of different duration. Columns start' +
+      ' at milliseconds, and each column is ten times longer: tens of' +
+      ' milliseconds, seconds, tens of seconds, etc.'
+};
+
+/**
+ * List of namespaces in Accumulo
+ */
+var NAMESPACES = '';
+
+/**
+ * Timer object
+ */
+var TIMER;

http://git-wip-us.apache.org/repos/asf/accumulo/blob/0ca5cd33/server/monitor/src/main/resources/resources/listType.js
----------------------------------------------------------------------
diff --git a/server/monitor/src/main/resources/resources/listType.js b/server/monitor/src/main/resources/resources/listType.js
new file mode 100644
index 0000000..8d74645
--- /dev/null
+++ b/server/monitor/src/main/resources/resources/listType.js
@@ -0,0 +1,140 @@
+/*
+* 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.
+*/
+var type, minutes;
+
+/**
+ * Makes the REST calls, generates the tables with the new information
+ */
+function refreshListType() {
+  $.ajaxSetup({
+    async: false
+  });
+  getTraceOfType(type, minutes);
+  $.ajaxSetup({
+    async: true
+  });
+  refreshTypeTraceTable(minutes);
+}
+
+/**
+ * Used to redraw the page
+ */
+function refresh() {
+  refreshListType();
+}
+
+/**
+ * Generates the trace per type table
+ *
+ * @param {string} minutes Minutes to display the trace
+ */
+function refreshTypeTraceTable(minutes) {
+  clearTable('trace');
+
+  /*
+   * Get the trace type value obtained earlier,
+   * if it doesn't exists, create an empty array
+   */
+  var data = sessionStorage.traceType === undefined ?
+      [] : JSON.parse(sessionStorage.traceType);
+  /*
+   * If the data is empty, create an empty row, otherwise,
+   * create the rows for the table
+   */
+  if (data.length === 0 || data.traces.length === 0) {
+    var items = [];
+    items.push('<td class="center" colspan="3"><i>No traces in the last ' +
+        minutes + ' minute(s)</i></td>');
+    $('<tr/>', {
+      html: items.join('')
+    }).appendTo('#trace');
+  } else {
+    $.each(data.traces, function(key, val) {
+      var items = [];
+
+      // Convert start value to a date
+      var date = new Date(val.start);
+      items.push('<td class="firstcell left"><a href="/trace/show?id=' +
+          val.id + '">' + date.toLocaleString() + '</a></td>');
+      items.push('<td class ="right">' + timeDuration(val.ms) + '</td>');
+      items.push('<td class="left">' + val.source + '</td>');
+
+      $('<tr/>', {
+        html: items.join('')
+      }).appendTo('#trace');
+    });
+  }
+}
+
+/**
+ * Sorts the trace table on the selected column
+ *
+ * @param {number} n Column number to sort by
+ */
+function sortTable(n) {
+  if (sessionStorage.tableColumnSort !== undefined &&
+      sessionStorage.tableColumnSort == n &&
+      sessionStorage.direction !== undefined) {
+    direction = sessionStorage.direction === 'asc' ? 'desc' : 'asc';
+  } else {
+    direction = sessionStorage.direction === undefined ?
+        'asc' : sessionStorage.direction;
+  }
+  sessionStorage.tableColumnSort = n;
+  sortTables('trace', direction, n);
+}
+
+/**
+ * Create tooltip for table column information
+ */
+$(function() {
+  $(document).tooltip();
+});
+
+/**
+ * Creates the trace type header
+ *
+ * @param {string} type2 Trace type to display
+ * @param {string} minutes2 Minutes to display trace
+ */
+function createHeader(type2, minutes2) {
+  var caption = [];
+  type = type2;
+  minutes = minutes2;
+
+  caption.push('<span class="table-caption">Traces for ' +
+      type + '</span><br />');
+
+  $('<caption/>', {
+    html: caption.join('')
+  }).appendTo('#trace');
+
+  var items = [];
+
+  /*
+   * Adds the columns, add sortTable function on click,
+   * if the column has a description, add title taken from the global.js
+   */
+  items.push('<th class="firstcell" title="' + descriptions['Trace Start'] +
+      '">Start&nbsp;</th>');
+  items.push('<th title="' + descriptions['Span Time'] + '">ms&nbsp;</th>');
+  items.push('<th title="' + descriptions['Source'] + '">Source&nbsp;</th>');
+
+  $('<tr/>', {
+    html: items.join('')
+  }).appendTo('#trace');
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/0ca5cd33/server/monitor/src/main/resources/resources/log.js
----------------------------------------------------------------------
diff --git a/server/monitor/src/main/resources/resources/log.js b/server/monitor/src/main/resources/resources/log.js
new file mode 100644
index 0000000..4c5adf9
--- /dev/null
+++ b/server/monitor/src/main/resources/resources/log.js
@@ -0,0 +1,173 @@
+/*
+* 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.
+*/
+
+/**
+ * Creates bulk import initial table
+ */
+$(document).ready(function() {
+  createHeader();
+  refreshLogs();
+});
+
+/**
+ * Makes the REST calls, generates the tables with the new information
+ */
+function refreshLogs() {
+  $.ajaxSetup({
+    async: false
+  });
+  getLogs();
+  $.ajaxSetup({
+    async: true
+  });
+  createHeader();
+  createLogsTable();
+}
+
+/**
+ * Used to redraw the page
+ */
+function refresh() {
+  refreshLogs();
+}
+
+/**
+ * Clears the log table
+ */
+function clearLogTable() {
+  clearLogs();
+  refreshLogs();
+  refreshNavBar();
+}
+
+/**
+ * Generates the log table
+ */
+function createLogsTable() {
+  clearTable('logTable');
+
+  /*
+   * Get the logs value obtained earlier,
+   * if it doesn't exists, create an empty array
+   */
+  var data = sessionStorage.logs === undefined ?
+      [] : JSON.parse(sessionStorage.logs);
+
+  /*
+   * If the data is empty, create an empty row, otherwise,
+   * create the rows for the table
+   */
+  if (data.length === 0) {
+    var items = [];
+    items.push('<td class="center" colspan="5"><i>Empty</i></td>');
+    $('<tr/>', {
+      html: items.join('')
+    }).appendTo('#logTable');
+  } else {
+    $.each(data, function(key, val) {
+      var items = [];
+      var date = new Date(val.timestamp);
+      items.push('<td class="firstcell left" data-value="' + val.timestamp +
+          '">' + date.toLocaleString().split(' ').join('&nbsp;') + '</td>');
+
+      items.push('<td class="center" data-value="' + val.application + '">' +
+          val.application + '</td>');
+
+      items.push('<td class="right" data-value="' + val.count + '">' +
+          bigNumberForQuantity(val.count) + '</td>');
+      items.push('<td class="center" data-value="' + val.level + '">' +
+          levelFormat(val.level) + '</td>');
+      items.push('<td class="center" data-value="' + val.message + '">' +
+          val.message + '</td>');
+
+      $('<tr/>', {
+        html: items.join('')
+      }).appendTo('#logTable');
+    });
+  }
+}
+
+/**
+ * Formats the log level as HTML
+ *
+ * @param {string} level Log level
+ * @return {string} HTML formatted level
+ */
+function levelFormat(level) {
+  if (level === 'WARN') {
+    return '<span class="label label-warning">' + level + '</span>';
+  } else if (level === 'ERROR' || level === 'FATAL') {
+    return '<span class="label label-danger">' + level + '</span>';
+  } else {
+    return level;
+  }
+}
+
+/**
+ * Sorts the logTable table on the selected column
+ *
+ * @param {number} n Column number to sort by
+ */
+function sortTable(n) {
+  if (sessionStorage.tableColumnSort !== undefined &&
+      sessionStorage.tableColumnSort == n &&
+      sessionStorage.direction !== undefined) {
+    direction = sessionStorage.direction === 'asc' ? 'desc' : 'asc';
+  } else {
+    direction = sessionStorage.direction === undefined ?
+        'asc' : sessionStorage.direction;
+  }
+  sessionStorage.tableColumnSort = n;
+  sortTables('logTable', direction, n);
+}
+
+/**
+ * Creates the log table header
+ */
+function createHeader() {
+  $('#logTable caption').remove();
+  var caption = [];
+
+  caption.push('<span class="table-caption">Recent Logs</span><br />');
+
+  var data = sessionStorage.logs === undefined ?
+      [] : JSON.parse(sessionStorage.logs);
+  if (data.length !== 0) {
+    caption.push('<a href="javascript:clearLogTable();">Clear&nbsp;' +
+        'All&nbsp;Events</a>');
+  }
+
+  $('<caption/>', {
+    html: caption.join('')
+  }).appendTo('#logTable');
+
+  var items = [];
+
+  /*
+   * Adds the columns, add sortTable function on click,
+   * if the column has a description, add title taken from the global.js
+   */
+  items.push('<th class="firstcell" onclick="sortTable(0)">Time&nbsp;</th>');
+  items.push('<th onclick="sortTable(1)">Application&nbsp;</th>');
+  items.push('<th onclick="sortTable(2)">Count&nbsp;</th>');
+  items.push('<th onclick="sortTable(3)">Level&nbsp;</th>');
+  items.push('<th onclick="sortTable(4)">Message&nbsp;</th>');
+
+  $('<tr/>', {
+    html: items.join('')
+  }).appendTo('#logTable');
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/0ca5cd33/server/monitor/src/main/resources/resources/master.js
----------------------------------------------------------------------
diff --git a/server/monitor/src/main/resources/resources/master.js b/server/monitor/src/main/resources/resources/master.js
new file mode 100644
index 0000000..bc98a97
--- /dev/null
+++ b/server/monitor/src/main/resources/resources/master.js
@@ -0,0 +1,265 @@
+/*
+* 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.
+*/
+
+/**
+ * Creates master initial table
+ */
+$(document).ready(function() {
+  createHeader();
+  doBanner('masterBanner', 'danger', 'Master Server Not Running');
+  refreshMaster();
+});
+
+/**
+ * Makes the REST calls, generates the tables with the new information
+ */
+function refreshMaster() {
+  $.ajaxSetup({
+    async: false
+  });
+  getMaster();
+  getRecoveryList();
+  $.ajaxSetup({
+    async: true
+  });
+  refreshMasterTable();
+  recoveryList();
+}
+
+
+/*
+ * The tables refresh function will do this functionality
+ * If tables are removed from Master, uncomment this function
+ */
+/**
+ * Used to redraw the page
+ */
+/*function refresh() {
+  refreshMaster();
+}*/
+
+/**
+ * Creates recovery list table
+ */
+function recoveryList() {
+  /*
+   * Get the recovery value obtained earlier,
+   * if it doesn't exists, create an empty array
+   */
+  var data = sessionStorage.recoveryList === undefined ?
+      [] : JSON.parse(sessionStorage.recoveryList);
+
+  $('#recoveryList tr').remove();
+
+  // If there is no recovery list data, hide the table
+  if (data.length === 0 || data.recoveryList.length === 0) {
+    $('#recoveryList').hide();
+  } else {
+    $('#recoveryList').show();
+
+    var caption = [];
+
+    caption.push('<span class="table-caption">Log&nbsp;Recovery</span><br />');
+    caption.push('<span class="table-subcaption">Some tablets were unloaded' +
+        ' in an unsafe manner. Write-ahead logs are being' +
+        ' recovered.</span><br />');
+
+    $('<caption/>', {
+      html: caption.join('')
+    }).appendTo('#recoveryList');
+
+    var items = [];
+
+    /*
+     * Create the header for the recovery list table
+     * Adds the columns, add sortTable function on click,
+     * if the column has a description, add title taken from the global.js
+     */
+    items.push('<th class="firstcell" onclick="sortTable(0)">' +
+        'Server&nbsp;</th>');
+    items.push('<th onclick="sortTable(1)">Log&nbsp;</th>');
+    items.push('<th onclick="sortTable(2)">Time&nbsp;</th>');
+    items.push('<th onclick="sortTable(3)">Copy/Sort&nbsp;</th>');
+
+    $('<tr/>', {
+      html: items.join('')
+    }).appendTo('#recoveryList');
+
+    // Creates the table for the recovery list
+    $.each(data.recoveryList, function(key, val) {
+      var items = [];
+      items.push('<td class="firstcell left" data-value="' + val.server + '">' +
+          val.server + '</td>');
+      items.push('<td class="right" data-value="' + val.log + '">' + val.log +
+          '</td>');
+      var date = new Date(parseInt(val.time));
+      date = date.toLocaleString().split(' ').join('&nbsp;');
+      items.push('<td class="right" data-value="' + val.time + '">' + date +
+          '</td>');
+      items.push('<td class="right" data-value="' + val.copySort + '">' +
+          val.copySort + '</td>');
+
+      $('<tr/>', {
+        html: items.join('')
+      }).appendTo('#recoveryList');
+    });
+  }
+}
+
+/**
+ * Generates the master table
+ */
+function refreshMasterTable() {
+  // Gets the master status
+  var status = JSON.parse(sessionStorage.status).masterStatus;
+
+  // Hide the banner and the master table
+  $('#masterBanner').hide();
+  $('#masterStatus tr:gt(0)').remove();
+  $('#masterStatus').hide();
+
+  // If master status is error, show banner, otherwise, create master table
+  if (status === 'ERROR') {
+    $('#masterBanner').show();
+  } else {
+    $('#masterStatus').show();
+    var data = JSON.parse(sessionStorage.master);
+    var items = [];
+    items.push('<td class="firstcell left" data-value="' + data.master +
+        '">' + data.master + '</td>');
+
+    items.push('<td class="right" data-value="' + data.onlineTabletServers +
+        '">' + data.onlineTabletServers + '</td>');
+
+    items.push('<td class="right" data-value="' + data.totalTabletServers +
+        '">' + data.totalTabletServers + '</td>');
+
+    var date = new Date(parseInt(data.lastGC));
+    date = date.toLocaleString().split(' ').join('&nbsp;');
+    items.push('<td class="left" data-value="' + data.lasGC +
+        '"><a href="/gc">' + date + '</a></td>');
+
+    items.push('<td class="right" data-value="' + data.tablets +
+        '">' + bigNumberForQuantity(data.tablets) + '</td>');
+
+    items.push('<td class="right" data-value="' + data.unassignedTablets +
+        '">' + bigNumberForQuantity(data.unassignedTablets) + '</td>');
+
+    items.push('<td class="right" data-value="' + data.numentries +
+        '">' + bigNumberForQuantity(data.numentries) + '</td>');
+
+    items.push('<td class="right" data-value="' + data.ingestrate +
+        '">' + bigNumberForQuantity(Math.round(data.ingestrate)) + '</td>');
+
+    items.push('<td class="right" data-value="' + data.entriesRead +
+        '">' + bigNumberForQuantity(Math.round(data.entriesRead)) + '</td>');
+
+    items.push('<td class="right" data-value="' + data.queryrate +
+        '">' + bigNumberForQuantity(Math.round(data.queryrate)) + '</td>');
+
+    items.push('<td class="right" data-value="' + data.holdTime +
+        '">' + timeDuration(data.holdTime) + '</td>');
+
+    items.push('<td class="right" data-value="' + data.osload +
+        '">' + bigNumberForQuantity(data.osload) + '</td>');
+
+    $('<tr/>', {
+     html: items.join('')
+    }).appendTo('#masterStatus');
+  }
+}
+
+/**
+ * Sorts the masterStatus table on the selected column
+ *
+ * @param {number} n Column number to sort by
+ */
+function sortTable(n) {
+  if (sessionStorage.tableColumnSort !== undefined &&
+      sessionStorage.tableColumnSort == n &&
+      sessionStorage.direction !== undefined) {
+    direction = sessionStorage.direction === 'asc' ? 'desc' : 'asc';
+  } else {
+    direction = sessionStorage.direction === undefined ?
+        'asc' : sessionStorage.direction;
+  }
+  sessionStorage.tableColumnSort = n;
+  sortTables('masterStatus', direction, n);
+}
+
+/**
+ * Create tooltip for table column information
+ */
+$(function() {
+  $(document).tooltip();
+});
+
+/**
+ * Creates the master header
+ */
+function createHeader() {
+  var caption = [];
+
+  caption.push('<span class="table-caption">Master&nbsp;Status</span><br />');
+
+  $('<caption/>', {
+    html: caption.join('')
+  }).appendTo('#masterStatus');
+
+  var items = [];
+
+  /*
+   * Adds the columns, add sortTable function on click,
+   * if the column has a description, add title taken from the global.js
+   */
+  items.push('<th class="firstcell" onclick="sortTable(0)" title="' +
+      descriptions['Master'] + '">Master&nbsp;</th>');
+
+  items.push('<th onclick="sortTable(1)" title="' +
+      descriptions['# Online Tablet Servers'] +
+      '">#&nbsp;Online<br />Tablet&nbsp;Servers&nbsp;</th>');
+
+  items.push('<th onclick="sortTable(2)" title="' +
+      descriptions['# Total Tablet Servers'] +
+      '">#&nbsp;Total<br />Tablet&nbsp;Servers&nbsp;</th>');
+
+  items.push('<th onclick="sortTable(3)" title="' +
+      descriptions['Last GC'] + '">Last&nbsp;GC&nbsp;</th>');
+
+  items.push('<th onclick="sortTable(4)" title="' +
+      descriptions['# Tablets'] + '">#&nbsp;Tablets&nbsp;</th>');
+
+  items.push('<th onclick="sortTable(5)">#&nbsp;Unassigned' +
+      '<br />Tablets&nbsp;</th>');
+  items.push('<th onclick="sortTable(6)" title="' +
+      descriptions['Total Entries'] + '">Entries&nbsp;</th>');
+  items.push('<th onclick="sortTable(7)" title="' +
+      descriptions['Total Ingest'] + '">Ingest&nbsp;</th>');
+  items.push('<th onclick="sortTable(8)" title="' +
+      descriptions['Total Entries Read'] + '">Entries<br />Read&nbsp;</th>');
+  items.push('<th onclick="sortTable(9)" title="' +
+      descriptions['Total Entries Returned'] +
+      '">Entries<br />Returned&nbsp;</th>');
+  items.push('<th onclick="sortTable(10)" title="' +
+      descriptions['Max Hold Time'] + '">Hold&nbsp;Time&nbsp;</th>');
+  items.push('<th onclick="sortTable(11)" title="' +
+      descriptions['OS Load'] + '">OS&nbsp;Load&nbsp;</th>');
+
+  $('<tr/>', {
+    html: items.join('')
+  }).appendTo('#masterStatus');
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/0ca5cd33/server/monitor/src/main/resources/resources/overview.js
----------------------------------------------------------------------
diff --git a/server/monitor/src/main/resources/resources/overview.js b/server/monitor/src/main/resources/resources/overview.js
new file mode 100644
index 0000000..272133f
--- /dev/null
+++ b/server/monitor/src/main/resources/resources/overview.js
@@ -0,0 +1,293 @@
+/*
+* 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.
+*/
+
+/**
+ * Creates overview initial tables
+ */
+$(document).ready(function() {
+  createMasterTable();
+  createZKTable();
+  refreshOverview();
+});
+
+/**
+ * Makes the REST calls, generates the tables with the new information
+ */
+function refreshOverview() {
+  $.ajaxSetup({
+    async: false
+  });
+  getMaster();
+  getZK();
+  getIngestRate();
+  getScanEntries();
+  getIngestByteRate();
+  getQueryByteRate();
+  getLoadAverage();
+  getLookups();
+  getMinorCompactions();
+  getMajorCompactions();
+  getIndexCacheHitRate();
+  getDataCacheHitRate();
+  $.ajaxSetup({
+    async: true
+  });
+  refreshMasterTable();
+  refreshZKTable();
+  makePlots();
+}
+
+/**
+ * Used to redraw the page
+ */
+function refresh() {
+  refreshOverview();
+}
+
+/**
+ * Refreshes the master table
+ */
+function refreshMasterTable() {
+  var data = sessionStorage.master === undefined ?
+      [] : JSON.parse(sessionStorage.master);
+
+  $('#master tr td:first').hide();
+  $('#master tr td').hide();
+
+  // If the master is down, show the first row, otherwise refresh old values
+  if (data.length === 0 || data.master === 'No Masters running') {
+    $('#master tr td:first').show();
+  } else {
+    $('#master tr td:not(:first)').show();
+    var table = $('#master td.right');
+
+    table.eq(0).html(bigNumberForQuantity(data.tables));
+    table.eq(1).html(bigNumberForQuantity(data.totalTabletServers));
+    table.eq(2).html(bigNumberForQuantity(data.deadTabletServersCount));
+    table.eq(3).html(bigNumberForQuantity(data.tablets));
+    table.eq(4).html(bigNumberForQuantity(data.numentries));
+    table.eq(5).html(bigNumberForQuantity(data.lookups));
+    table.eq(6).html(timeDuration(data.uptime));
+  }
+}
+
+/**
+ * Generates the master table
+ */
+function createMasterTable() {
+  var items = [];
+  items.push('<tr><th colspan="2"><a href="/master">Accumulo' +
+      '&nbsp;Master</a></th></tr>');
+
+  items.push('<tr><td colspan="2" class="center">' +
+      '<span class="label label-danger">Master is Down</span></td></tr>');
+
+  items.push('<tr><td class="left"><a href="/tables">Tables</a></td>' +
+      '<td class="right"></td></tr>');
+
+  items.push('<tr><td class="left"><a href="/tservers">Tablet' +
+      '&nbsp;Servers</a></td><td class="right"></td></tr>');
+
+  items.push('<tr><td class="left"><a href="/tservers">Dead&nbsp;' +
+      'Tablet&nbsp;Servers</a></td><td class="right"></td></tr>');
+
+  items.push('<tr><td class="left">Tablets</td><td class="right"></td></tr>');
+  items.push('<tr><td class="left">Entries</td><td class="right"></td></tr>');
+  items.push('<tr><td class="left">Lookups</td><td class="right"></td></tr>');
+  items.push('<tr><td class="left">Uptime</td><td class="right"></td></tr>');
+
+  $('<table/>', {
+    html: items.join(''),
+    class: 'table table-bordered table-striped table-condensed'
+  }).appendTo('#master');
+}
+
+/**
+ * Refresh the zookeeper table
+ */
+function refreshZKTable() {
+  var data = sessionStorage.zk === undefined ?
+      [] : JSON.parse(sessionStorage.zk);
+
+  $('#zookeeper tr td:first').hide();
+  $('#zookeeper tr:gt(2)').remove();
+
+  if (data.length === 0 || data.zkServers.length === 0) {
+    $('#zookeeper tr td:first').show();
+  } else {
+    var items = [];
+    $.each(data.zkServers, function(key, val) {
+      if (val.clients >= 0) {
+        items.push('<td class="left">' + val.server + '</td>');
+        items.push('<td class="left">' + val.mode + '</td>');
+        items.push('<td class="right">' + val.clients + '</td></tr>');
+      } else {
+        items.push('<tr><td class="left">' + val.server + '</td>');
+        items.push('<td class="left"><span class="error">Down</span></td>');
+        items.push('<td class="right"></td>');
+      }
+    });
+    $('<tr/>', {
+      html: items.join('')
+    }).appendTo('#zookeeper table');
+  }
+}
+
+/**
+ * Generates the zookeeper table
+ */
+function createZKTable() {
+  var items = [];
+  items.push('<tr><th colspan="3">Zookeeper</th></tr>');
+  items.push('<tr><th>Server</th><th>Mode</th><th>Clients</th></tr>');
+  items.push('<td class="center" colspan="3"><i>No Zookeepers</i></td>');
+  $('<table/>', {
+    html: items.join(''),
+    class: 'table table-bordered table-striped table-condensed'
+  }).appendTo('#zookeeper');
+}
+
+//// Overview plot creation
+
+/**
+ * Create the plots for the overview page
+ */
+function makePlots() {
+  var d = new Date();
+  var n = d.getTimezoneOffset() * 60000; // Converts offset to milliseconds
+  var tz = new Date().toLocaleTimeString('en-us',
+      {timeZoneName: 'short'}).split(' ')[2]; // Short version of timezone
+  var tzFormat = '%H:%M<br />' + tz;
+
+  // Create Ingest Rate plot
+  var ingestRate = [];
+  var data = sessionStorage.ingestRate === undefined ?
+      [] : JSON.parse(sessionStorage.ingestRate);
+  $.each(data, function(key, val) {
+
+    ingestRate.push([val.first - n, val.second]);
+  });
+  $.plot($('#ingest_entries'), [{ data: ingestRate,
+      lines: { show: true }, color: '#d9534f' }],
+      {yaxis: {}, xaxis: {mode: 'time', minTickSize: [1, 'minute'],
+      timeformat: tzFormat, ticks: 3}});
+
+  // Create Scan Entries plot
+  var scanEntries = {'Read': [], 'Returned': []};
+  var data = sessionStorage.scanEntries === undefined ?
+      [] : JSON.parse(sessionStorage.scanEntries);
+  $.each(data, function(key, val) {
+    $.each(val.second, function(key2, val2) {
+      scanEntries[val.first].push([val2.first - n, val2.second]);
+    });
+  });
+  $.plot($('#scan_entries'), [{ label: 'Read',
+      data: scanEntries.Read, lines: { show: true }, color: '#d9534f' },
+      { label: 'Returned', data: scanEntries.Returned, lines: { show: true },
+      color: '#337ab7' }], {yaxis: {}, xaxis: {mode: 'time',
+      minTickSize: [1, 'minute'], timeformat: tzFormat, ticks: 3}});
+
+  // Create Ingest MB plot
+  var ingestMB = [];
+  var data = sessionStorage.ingestMB === undefined ?
+      [] : JSON.parse(sessionStorage.ingestMB);
+  $.each(data, function(key, val) {
+    ingestMB.push([val.first - n, val.second]);
+  });
+  $.plot($('#ingest_mb'), [{ data: ingestMB, lines: { show: true },
+      color: '#d9534f' }], {yaxis: {}, xaxis: {mode: 'time',
+      minTickSize: [1, 'minute'], timeformat: tzFormat, ticks: 3}});
+
+  // Create Query MB plot
+  var queryMB = [];
+  var data = sessionStorage.queryMB === undefined ?
+      [] : JSON.parse(sessionStorage.queryMB);
+  $.each(data, function(key, val) {
+  queryMB.push([val.first - n, val.second]);
+  });
+  $.plot($('#scan_mb'), [{ data: queryMB, lines: { show: true },
+      color: '#d9534f' }], {yaxis: {}, xaxis: {mode: 'time',
+      minTickSize: [1, 'minute'], timeformat: tzFormat, ticks: 3}});
+
+  // Create Load Average plot
+  var loadAvg = [];
+  var data = sessionStorage.loadAvg === undefined ?
+      [] : JSON.parse(sessionStorage.loadAvg);
+  $.each(data, function(key, val) {
+    loadAvg.push([val.first - n, val.second]);
+  });
+  $.plot($('#load_avg'), [{ data: loadAvg, lines: { show: true },
+      color: '#d9534f' }], {yaxis: {}, xaxis: {mode: 'time',
+      minTickSize: [1, 'minute'], timeformat: tzFormat, ticks: 3}});
+
+  // Create Seeks plot
+  var lookups = [];
+  var data = sessionStorage.lookups === undefined ?
+      [] : JSON.parse(sessionStorage.lookups);
+  $.each(data, function(key, val) {
+    lookups.push([val.first - n, val.second]);
+  });
+  $.plot($('#seeks'), [{ data: lookups, lines: { show: true },
+      color: '#d9534f' }], {yaxis: {}, xaxis: {mode: 'time',
+      minTickSize: [1, 'minute'], timeformat: tzFormat, ticks: 3}});
+
+  // Create Minor Compactions plot
+  var minor = [];
+  var data = sessionStorage.minorCompactions === undefined ?
+      [] : JSON.parse(sessionStorage.minorCompactions);
+  $.each(data, function(key, val) {
+    minor.push([val.first - n, val.second]);
+  });
+  $.plot($('#minor'), [{ data: minor, lines: { show: true },
+      color: '#d9534f' }], {yaxis: {}, xaxis: {mode: 'time',
+      minTickSize: [1, 'minute'], timeformat: tzFormat, ticks: 3}});
+
+  // Create Major Compaction plot
+  var major = [];
+  var data = sessionStorage.majorCompactions === undefined ?
+      [] : JSON.parse(sessionStorage.majorCompactions);
+  $.each(data, function(key, val) {
+    major.push([val.first - n, val.second]);
+  });
+  $.plot($('#major'), [{ data: major, lines: { show: true },
+      color: '#d9534f' }], {yaxis: {}, xaxis: {mode: 'time',
+      minTickSize: [1, 'minute'], timeformat: tzFormat, ticks: 3}});
+
+  // Create Index Cache plot
+  var indexCache = [];
+  var data = sessionStorage.indexCache === undefined ?
+      [] : JSON.parse(sessionStorage.indexCache);
+  $.each(data, function(key, val) {
+    indexCache.push([val.first - n, val.second]);
+  });
+  $.plot($('#index_cache'), [{ data: indexCache,
+      points: { show: true, radius: 1 }, color: '#d9534f' }],
+      {yaxis: {}, xaxis: {mode: 'time', minTickSize: [1, 'minute'],
+      timeformat: tzFormat, ticks: 3}});
+
+  // Create Data Cache plot
+  var dataCache = [];
+  var data = sessionStorage.dataCache === undefined ?
+      [] : JSON.parse(sessionStorage.dataCache);
+  $.each(data, function(key, val) {
+    dataCache.push([val.first - n, val.second]);
+  });
+  $.plot($('#data_cache'), [{ data: dataCache,
+      points: { show: true, radius: 1 }, color: '#d9534f' }],
+      {yaxis: {}, xaxis: {mode: 'time', minTickSize: [1, 'minute'],
+      timeformat: tzFormat, ticks: 3}});
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/0ca5cd33/server/monitor/src/main/resources/resources/problems.js
----------------------------------------------------------------------
diff --git a/server/monitor/src/main/resources/resources/problems.js b/server/monitor/src/main/resources/resources/problems.js
new file mode 100644
index 0000000..520ebc2
--- /dev/null
+++ b/server/monitor/src/main/resources/resources/problems.js
@@ -0,0 +1,232 @@
+/*
+* 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.
+*/
+
+/**
+ * Makes the REST calls, generates the tables with the new information
+ */
+function refreshProblems() {
+  $.ajaxSetup({
+    async: false
+  });
+  getProblems();
+  $.ajaxSetup({
+    async: true
+  });
+  refreshProblemSummaryTable();
+  refreshProblemDetailsTable();
+}
+
+/**
+ * Used to redraw the page
+ */
+function refresh() {
+  refreshProblems();
+}
+
+/**
+ * Makes REST POST call to clear the problem summary table
+ *
+ * @param {string} tableID Table ID to clear
+ */
+function clearTableProblemsTable(tableID) {
+  clearTableProblems(tableID);
+  refreshProblems();
+  refreshNavBar();
+}
+
+/**
+ * Makes REST POST call to clear the problem details table
+ *
+ * @param {string} table Table ID to clear
+ * @param {string} resource Resource of problem
+ * @param {string} type Type of problem
+ */
+function clearDetailsProblemsTable(table, resource, type) {
+  clearDetailsProblems(table, resource, type);
+  refreshProblems();
+  refreshNavBar();
+}
+
+/**
+ * Generates the problem summary table
+ */
+function refreshProblemSummaryTable() {
+  clearTable('problemSummary');
+  var data = sessionStorage.problemSummary === undefined ?
+      [] : JSON.parse(sessionStorage.problemSummary);
+
+  if (data.length === 0 || Object.keys(data.problemSummary).length === 0) {
+    var items = [];
+    items.push('<td class="center" colspan="5"><i>Empty</i></td>');
+    $('<tr/>', {
+      html: items.join('')
+    }).appendTo('#problemSummary');
+  } else {
+    $.each(data.problemSummary, function(key, val) {
+      var items = [];
+      items.push('<td class="firstcell left"><a href="/problems?table=' +
+          val.tableID.split('+').join('%2B') + '">' + val.tableName +
+          '</a></td>');
+
+      items.push('<td class="right">' + bigNumberForQuantity(val.fileRead) +
+          '</td>');
+
+      items.push('<td class="right">' + bigNumberForQuantity(val.fileWrite) +
+          '</td>');
+
+      items.push('<td class="right">' + bigNumberForQuantity(val.tableLoad) +
+          '</td>');
+      items.push('<td><a href="javascript:clearTableProblemsTable(\'' +
+          val.tableID + '\');">clear ALL ' + val.tableName +
+          ' problems</a></td>');
+
+      $('<tr/>', {
+        html: items.join('')
+      }).appendTo('#problemSummary');
+    });
+  }
+}
+
+/**
+ * Generates the problem details table
+ */
+function refreshProblemDetailsTable() {
+  clearTable('problemDetails');
+  var data = sessionStorage.problemDetails === undefined ?
+      [] : JSON.parse(sessionStorage.problemDetails);
+
+  if (data.length === 0 || Object.keys(data.problemDetails).length === 0) {
+    var items = [];
+    items.push('<td class="center" colspan="7"><i>Empty</i></td>');
+    $('<tr/>', {
+      html: items.join('')
+    }).appendTo('#problemDetails');
+  } else {
+    $.each(data.problemDetails, function(key, val) {
+      var items = [];
+      // Filters the details problems for the selected tableID
+      if (tableID === val.tableID || tableID === '') {
+        items.push('<td class="firstcell left" data-value="' + val.tableName +
+            '"><a href="/tables/' + val.tableID + '">' + val.tableName +
+            '</a></td>');
+
+        items.push('<td class="right" data-value="' + val.type + '">' +
+            val.type + '</td>');
+
+        items.push('<td class="right" data-value="' + val.server + '">' +
+            val.server + '</td>');
+
+        var date = new Date(val.time);
+        items.push('<td class="right" data-value="' + val.time + '">' +
+            date.toLocaleString() + '</td>');
+
+        items.push('<td class="right" data-value="' + val.resource + '">' +
+            val.resource + '</td>');
+
+        items.push('<td class="right" data-value="' + val.exception + '">' +
+            val.exception + '</td>');
+
+        items.push('<td><a href="javascript:clearDetailsProblemsTable(\'' +
+            val.tableID + '\', \'' + val.resource + '\', \'' + val.type +
+            '\')">clear this problem</a></td>');
+      }
+
+      $('<tr/>', {
+        html: items.join('')
+      }).appendTo('#problemDetails');
+
+    });
+  }
+}
+
+/**
+ * Sorts the problemDetails table on the selected column
+ *
+ * @param {number} n Column number to sort by
+ */
+function sortTable(n) {
+  if (sessionStorage.tableColumnSort !== undefined &&
+      sessionStorage.tableColumnSort == n &&
+      sessionStorage.direction !== undefined) {
+    direction = sessionStorage.direction === 'asc' ? 'desc' : 'asc';
+  } else {
+    direction = sessionStorage.direction === undefined ?
+        'asc' : sessionStorage.direction;
+  }
+
+  sessionStorage.tableColumnSort = n;
+
+  sortTables('problemDetails', direction, n);
+}
+
+/**
+ * Creates the problem summary header
+ */
+function createSummaryHeader() {
+  var caption = [];
+
+  caption.push('<span class="table-caption">Problem&nbsp;Summary</span><br />');
+
+  $('<caption/>', {
+    html: caption.join('')
+  }).appendTo('#problemSummary');
+
+  var items = [];
+
+  items.push('<th class="firstcell">Table&nbsp;</th>');
+  items.push('<th>FILE_READ&nbsp;</th>');
+  items.push('<th>FILE_WRITE&nbsp;</th>');
+  items.push('<th>TABLET_LOAD&nbsp;</th>');
+  items.push('<th>Operations&nbsp;</th>');
+
+  $('<tr/>', {
+      html: items.join('')
+  }).appendTo('#problemSummary');
+}
+
+var tableID;
+/**
+ * Creates the problem detail header
+ *
+ * @param {string} table Table ID of problem
+ */
+function createDetailsHeader(table) {
+  tableID = table;
+  var caption = [];
+
+  caption.push('<span class="table-caption">Problem&nbsp;Details</span><br />');
+  caption.push('<span class="table-subcaption">Problems' +
+      '&nbsp;identified&nbsp;with&nbsp;tables.</span><br />');
+
+  $('<caption/>', {
+    html: caption.join('')
+  }).appendTo('#problemDetails');
+
+  var items = [];
+
+  items.push('<th class="firstcell" onclick="sortTable(0)">Table&nbsp;</th>');
+  items.push('<th onclick="sortTable(1)">Problem&nbsp;Type&nbsp;</th>');
+  items.push('<th onclick="sortTable(2)">Server&nbsp;</th>');
+  items.push('<th onclick="sortTable(3)">Time&nbsp;</th>');
+  items.push('<th onclick="sortTable(4)">Resource&nbsp;</th>');
+  items.push('<th onclick="sortTable(5)">Exception&nbsp;</th>');
+  items.push('<th>Operations&nbsp;</th>');
+
+  $('<tr/>', {
+    html: items.join('')
+  }).appendTo('#problemDetails');
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/0ca5cd33/server/monitor/src/main/resources/resources/replication.js
----------------------------------------------------------------------
diff --git a/server/monitor/src/main/resources/resources/replication.js b/server/monitor/src/main/resources/resources/replication.js
new file mode 100644
index 0000000..7b9bbe3
--- /dev/null
+++ b/server/monitor/src/main/resources/resources/replication.js
@@ -0,0 +1,137 @@
+/*
+* 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.
+*/
+
+/**
+ * Creates replication initial table
+ */
+$(document).ready(function() {
+  createHeader();
+  refreshReplication();
+});
+
+/**
+ * Makes the REST calls, generates the tables with the new information
+ */
+function refreshReplication() {
+  $.ajaxSetup({
+    async: false
+  });
+  getReplication();
+  $.ajaxSetup({
+    async: true
+  });
+  refreshReplicationsTable();
+}
+
+/**
+ * Used to redraw the page
+ */
+function refresh() {
+  refreshReplication();
+}
+
+/**
+ * Generates the replication table
+ */
+function refreshReplicationsTable() {
+  clearTable('replicationStats');
+
+  var data = sessionStorage.replication === undefined ?
+      [] : JSON.parse(sessionStorage.replication);
+
+  if (data.length === 0) {
+    var items = [];
+    items.push('<td class="center" colspan="5"><i>Replication ' +
+        'table is offline</i></td>');
+    $('<tr/>', {
+      html: items.join('')
+    }).appendTo('#replicationStats');
+  } else {
+    $.each(data, function(key, val) {
+      var items = [];
+      items.push('<td class="firstcell left" data-value="' + val.tableName +
+          '">' + val.tableName + '</td>');
+
+      items.push('<td class="right" data-value="' + val.peerName +
+          '">' + val.peerName + '</td>');
+
+      items.push('<td class="right" data-value="' + val.remoteIdentifier +
+          '">' + val.remoteIdentifier + '</td>');
+
+      items.push('<td class="right" data-value="' + val.replicaSystemType +
+          '">' + val.replicaSystemType + '</td>');
+
+      items.push('<td class="right" data-value="' +
+          val.filesNeedingReplication + '">' +
+          bigNumberForQuantity(val.filesNeedingReplication) + '</td>');
+
+      $('<tr/>', {
+        html: items.join('')
+      }).appendTo('#replicationStats');
+
+    });
+  }
+}
+
+/**
+ * Sorts the replicationStats table on the selected column
+ *
+ * @param {number} n Column number to sort by
+ */
+function sortTable(n) {
+
+  if (sessionStorage.tableColumnSort !== undefined &&
+      sessionStorage.tableColumnSort == n &&
+      sessionStorage.direction !== undefined) {
+    direction = sessionStorage.direction === 'asc' ? 'desc' : 'asc';
+  } else {
+    direction = sessionStorage.direction === undefined ?
+        'asc' : sessionStorage.direction;
+  }
+  sessionStorage.tableColumnSort = n;
+  sortTables('replicationStats', direction, n);
+}
+
+/**
+ * Creates the replication header
+ */
+function createHeader() {
+  var caption = [];
+
+  caption.push('<span class="table-caption">Replication Status</span><br />');
+
+  $('<caption/>', {
+    html: caption.join('')
+  }).appendTo('#replicationStats');
+
+  var items = [];
+
+  /*
+   * Adds the columns, add sortTable function on click
+   */
+  items.push('<th class="firstcell" onclick="sortTable(0)">Table&nbsp;</th>');
+  items.push('<th onclick="sortTable(1)">Peer&nbsp;</th>');
+  items.push('<th onclick="sortTable(2)">Remote&nbsp;Identifier&nbsp;</th>');
+  items.push('<th onclick="sortTable(3)">Replica&nbsp;' +
+      'System&nbsp;Type&nbsp;</th>');
+  items.push('<th onclick="sortTable(4)">Files&nbsp;' +
+      'needing&nbsp;replication&nbsp;</th>');
+
+  $('<tr/>', {
+    html: items.join('')
+  }).appendTo('#replicationStats');
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/0ca5cd33/server/monitor/src/main/resources/resources/scans.js
----------------------------------------------------------------------
diff --git a/server/monitor/src/main/resources/resources/scans.js b/server/monitor/src/main/resources/resources/scans.js
new file mode 100644
index 0000000..c4731f6
--- /dev/null
+++ b/server/monitor/src/main/resources/resources/scans.js
@@ -0,0 +1,133 @@
+/*
+* 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.
+*/
+
+/**
+ * Creates scans initial table
+ */
+$(document).ready(function() {
+  createHeader();
+  refreshScans();
+});
+
+/**
+ * Makes the REST calls, generates the tables with the new information
+ */
+function refreshScans() {
+  $.ajaxSetup({
+    async: false
+  });
+  getScans();
+  $.ajaxSetup({
+    async: true
+  });
+  refreshScansTable();
+}
+
+/**
+ * Used to redraw the page
+ */
+function refresh() {
+  refreshScans();
+}
+
+/**
+ * Generates the scans table
+ */
+function refreshScansTable() {
+  clearTable('scanStatus');
+
+  var data = sessionStorage.scans === undefined ?
+      [] : JSON.parse(sessionStorage.scans);
+
+  if (data.length === 0 || data.scans.length === 0) {
+    var items = '<td class="center" colspan="3"><i>Empty</i></td>';
+
+    $('<tr/>', {
+      html: items
+    }).appendTo('#scanStatus');
+  } else {
+    $.each(data.scans, function(key, val) {
+      var items = [];
+
+      items.push('<td class="firstcell left" data-value="' + val.server +
+          '"><a href="/tservers?s=' + val.server + '">' + val.server +
+          '</a></td>');
+
+      items.push('<td class="right" data-value="' + val.scanCount + '">' +
+          val.scanCount + '</td>');
+
+      items.push('<td class="right" data-value="' + val.oldestScan + '">' +
+          timeDuration(val.oldestScan) + '</td>');
+
+      $('<tr/>', {
+        html: items.join('')
+      }).appendTo('#scanStatus');
+    });
+  }
+}
+
+/**
+ * Sorts the scanStatus table on the selected column
+ *
+ * @param {number} n Column number to sort by
+ */
+function sortTable(n) {
+  if (sessionStorage.tableColumnSort !== undefined &&
+      sessionStorage.tableColumnSort == n &&
+      sessionStorage.direction !== undefined) {
+    direction = sessionStorage.direction === 'asc' ? 'desc' : 'asc';
+  } else {
+    direction = sessionStorage.direction === undefined ?
+        'asc' : sessionStorage.direction;
+  }
+  sessionStorage.tableColumnSort = n;
+  sortTables('scanStatus', direction, n);
+}
+
+/**
+ * Create tooltip for table column information
+ */
+$(function() {
+  $(document).tooltip();
+});
+
+/**
+ * Creates the scans header
+ */
+function createHeader() {
+  var caption = [];
+
+  caption.push('<span class="table-caption">Scan&nbsp;Status</span><br />');
+
+  $('<caption/>', {
+    html: caption.join('')
+  }).appendTo('#scanStatus');
+
+  var items = [];
+
+  items.push('<th class="firstcell" onclick="sortTable(0)">Server&nbsp;</th>');
+
+  items.push('<th onclick="sortTable(1)" title="' +
+      descriptions['# Scans'] + '">#&nbsp;</th>');
+
+  items.push('<th onclick="sortTable(2)" title="' +
+      descriptions['Oldest Scan'] + '">Oldest&nbsp;Age&nbsp;</th>');
+
+  $('<tr/>', {
+    html: items.join('')
+  }).appendTo('#scanStatus');
+}


Mime
View raw message