Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id E8856200CBD for ; Thu, 6 Jul 2017 22:43:04 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id E732E167626; Thu, 6 Jul 2017 20:43:04 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 32847167627 for ; Thu, 6 Jul 2017 22:43:01 +0200 (CEST) Received: (qmail 66081 invoked by uid 500); 6 Jul 2017 20:43:00 -0000 Mailing-List: contact commits-help@accumulo.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@accumulo.apache.org Delivered-To: mailing list commits@accumulo.apache.org Received: (qmail 64687 invoked by uid 99); 6 Jul 2017 20:42:58 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 06 Jul 2017 20:42:58 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 815ACF551A; Thu, 6 Jul 2017 20:42:55 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: ctubbsii@apache.org To: commits@accumulo.apache.org Date: Thu, 06 Jul 2017 20:43:06 -0000 Message-Id: In-Reply-To: <3b8d0f56f4e142fcbb35fd820ce25ed9@git.apache.org> References: <3b8d0f56f4e142fcbb35fd820ce25ed9@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [12/54] [abbrv] accumulo git commit: ACCUMULO-2181/3005 Porting Monitor archived-at: Thu, 06 Jul 2017 20:43:05 -0000 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 '—'; + } + + // 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' + ' ' + 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' + ' ' + 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' + ' ' + 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' + ' ' + hr + 'h'; + } + + // Obtains the years, if time is 0, return years, days, and units + yr = Math.floor(time); + return yr + 'y' + ' ' + 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(''); + } else if (dir == 'desc') { + $(h).append(''); + } + } + + /* + * 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 === '—' ? + null : (Number(x) == x ? Number(x) : x)); + + y = rows[i + 1].getElementsByTagName('td')[n].getAttribute('data-value'); + yFinal = (y === '-' || y === '—' ? + 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) { + $('
', { + 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 = 'No Collection Activity' + + ''; + + $('', { + 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('File Collection, Last Cycle"'); + + var date = new Date(working.finished); + items.push('' + date.toLocaleString() + ''); + + items.push('' + bigNumberForQuantity(working.candidates) + ''); + + items.push('' + bigNumberForQuantity(working.deleted) + ''); + + items.push('' + bigNumberForQuantity(working.inUse) + ''); + + items.push('' + bigNumberForQuantity(working.errors) + ''); + + items.push('' + + timeDuration(working.finished - working.started) + ''); + + $('', { + html: items.join('') + }).appendTo('#gcActivity'); + } + + // File Collection Running row + if (data.files.currentCycle.started > 0) { + var items = []; + + var working = data.files.currentCycle; + + items.push('File Collection, Running'); + + var date = new Date(working.finished); + items.push('' + date.toLocaleString() + ''); + + items.push('' + bigNumberForQuantity(working.candidates) + ''); + + items.push('' + bigNumberForQuantity(working.deleted) + ''); + + items.push('' + bigNumberForQuantity(working.inUse) + ''); + + items.push('' + bigNumberForQuantity(working.errors) + ''); + + items.push('' + + timeDuration(working.finished - working.started) + ''); + + $('', { + 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('WAL Collection, Last Cycle'); + + var date = new Date(working.finished); + items.push('' + date.toLocaleString() + ''); + + items.push('' + bigNumberForQuantity(working.candidates) + ''); + + items.push('' + bigNumberForQuantity(working.deleted) + ''); + + items.push('' + bigNumberForQuantity(working.inUse) + ''); + + items.push('' + bigNumberForQuantity(working.errors) + ''); + + items.push('' + + timeDuration(working.finished - working.started) + ''); + + $('', { + html: items.join('') + }).appendTo('#gcActivity'); + } + + // WAL Collection Running row + if (data.wals.currentCycle.started > 0) { + var items = []; + + var working = data.wals.currentCycle; + + items.push('WAL Collection, Running'); + + var date = new Date(working.finished); + items.push('' + date.toLocaleString() + ''); + + items.push('' + bigNumberForQuantity(working.candidates) + ''); + + items.push('' + bigNumberForQuantity(working.deleted) + ''); + + items.push('' + bigNumberForQuantity(working.inUse) + ''); + + items.push('' + bigNumberForQuantity(working.errors) + ''); + + items.push('' + + timeDuration(working.finished - working.started) + ''); + + $('', { + 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('Collection ' + + 'Activity
'); + + $('', { + 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('Activity' + + ' '); + items.push('Finished '); + items.push('Candidates '); + items.push('Deleted '); + items.push('In Use '); + items.push('Errors '); + items.push('Duration '); + + $('', { + 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('No traces in the last ' + + minutes + ' minute(s)'); + $('', { + 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('' + date.toLocaleString() + ''); + items.push('' + timeDuration(val.ms) + ''); + items.push('' + val.source + ''); + + $('', { + 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('Traces for ' + + type + '
'); + + $('', { + 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('Start '); + items.push('ms '); + items.push('Source '); + + $('', { + 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('Empty'); + $('', { + html: items.join('') + }).appendTo('#logTable'); + } else { + $.each(data, function(key, val) { + var items = []; + var date = new Date(val.timestamp); + items.push('' + date.toLocaleString().split(' ').join(' ') + ''); + + items.push('' + + val.application + ''); + + items.push('' + + bigNumberForQuantity(val.count) + ''); + items.push('' + + levelFormat(val.level) + ''); + items.push('' + + val.message + ''); + + $('', { + 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 '' + level + ''; + } else if (level === 'ERROR' || level === 'FATAL') { + return '' + level + ''; + } 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('Recent Logs
'); + + var data = sessionStorage.logs === undefined ? + [] : JSON.parse(sessionStorage.logs); + if (data.length !== 0) { + caption.push('Clear ' + + 'All Events'); + } + + $('', { + 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('Time '); + items.push('Application '); + items.push('Count '); + items.push('Level '); + items.push('Message '); + + $('', { + 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('Log Recovery
'); + caption.push('Some tablets were unloaded' + + ' in an unsafe manner. Write-ahead logs are being' + + ' recovered.
'); + + $('', { + 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('' + + 'Server '); + items.push('Log '); + items.push('Time '); + items.push('Copy/Sort '); + + $('', { + html: items.join('') + }).appendTo('#recoveryList'); + + // Creates the table for the recovery list + $.each(data.recoveryList, function(key, val) { + var items = []; + items.push('' + + val.server + ''); + items.push('' + val.log + + ''); + var date = new Date(parseInt(val.time)); + date = date.toLocaleString().split(' ').join(' '); + items.push('' + date + + ''); + items.push('' + + val.copySort + ''); + + $('', { + 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('' + data.master + ''); + + items.push('' + data.onlineTabletServers + ''); + + items.push('' + data.totalTabletServers + ''); + + var date = new Date(parseInt(data.lastGC)); + date = date.toLocaleString().split(' ').join(' '); + items.push('' + date + ''); + + items.push('' + bigNumberForQuantity(data.tablets) + ''); + + items.push('' + bigNumberForQuantity(data.unassignedTablets) + ''); + + items.push('' + bigNumberForQuantity(data.numentries) + ''); + + items.push('' + bigNumberForQuantity(Math.round(data.ingestrate)) + ''); + + items.push('' + bigNumberForQuantity(Math.round(data.entriesRead)) + ''); + + items.push('' + bigNumberForQuantity(Math.round(data.queryrate)) + ''); + + items.push('' + timeDuration(data.holdTime) + ''); + + items.push('' + bigNumberForQuantity(data.osload) + ''); + + $('', { + 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('Master Status
'); + + $('', { + 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('Master '); + + items.push('# Online
Tablet Servers '); + + items.push('# Total
Tablet Servers '); + + items.push('Last GC '); + + items.push('# Tablets '); + + items.push('# Unassigned' + + '
Tablets '); + items.push('Entries '); + items.push('Ingest '); + items.push('Entries
Read '); + items.push('Entries
Returned '); + items.push('Hold Time '); + items.push('OS Load '); + + $('', { + 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('Accumulo' + + ' Master'); + + items.push('' + + 'Master is Down'); + + items.push('Tables' + + ''); + + items.push('Tablet' + + ' Servers'); + + items.push('Dead ' + + 'Tablet Servers'); + + items.push('Tablets'); + items.push('Entries'); + items.push('Lookups'); + items.push('Uptime'); + + $('', { + 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(''); + items.push(''); + items.push(''); + } else { + items.push(''); + items.push(''); + items.push(''); + } + }); + $('', { + html: items.join('') + }).appendTo('#zookeeper table'); + } +} + +/** + * Generates the zookeeper table + */ +function createZKTable() { + var items = []; + items.push(''); + items.push(''); + items.push(''); + $('
' + val.server + '' + val.mode + '' + val.clients + '
' + val.server + 'Down
Zookeeper
ServerModeClients
No Zookeepers
', { + 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
' + 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(''); + $('', { + html: items.join('') + }).appendTo('#problemSummary'); + } else { + $.each(data.problemSummary, function(key, val) { + var items = []; + items.push(''); + + items.push(''); + + items.push(''); + + items.push(''); + items.push(''); + + $('', { + 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(''); + $('', { + 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(''); + + items.push(''); + + items.push(''); + + var date = new Date(val.time); + items.push(''); + + items.push(''); + + items.push(''); + + items.push(''); + } + + $('', { + 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('Problem Summary
'); + + $(''); + items.push(''); + items.push(''); + items.push(''); + items.push(''); + + $('', { + 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('Problem Details
'); + caption.push('Problems' + + ' identified with tables.
'); + + $(''); + items.push(''); + items.push(''); + items.push(''); + items.push(''); + items.push(''); + items.push(''); + + $('', { + 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(''); + $('', { + html: items.join('') + }).appendTo('#replicationStats'); + } else { + $.each(data, function(key, val) { + var items = []; + items.push(''); + + items.push(''); + + items.push(''); + + items.push(''); + + items.push(''); + + $('', { + 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('Replication Status
'); + + $(''); + items.push(''); + items.push(''); + items.push(''); + items.push(''); + + $('', { + 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 = ''; + + $('', { + html: items + }).appendTo('#scanStatus'); + } else { + $.each(data.scans, function(key, val) { + var items = []; + + items.push(''); + + items.push(''); + + items.push(''); + + $('', { + 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('Scan Status
'); + + $(''); + + items.push(''); + + items.push(''); + + $('', { + html: items.join('') + }).appendTo('#scanStatus'); +}
Empty
' + val.tableName + + '' + bigNumberForQuantity(val.fileRead) + + '' + bigNumberForQuantity(val.fileWrite) + + '' + bigNumberForQuantity(val.tableLoad) + + 'clear ALL ' + val.tableName + + ' problems
Empty
' + val.tableName + + '' + + val.type + '' + + val.server + '' + + date.toLocaleString() + '' + + val.resource + '' + + val.exception + 'clear this problem
', { + html: caption.join('') + }).appendTo('#problemSummary'); + + var items = []; + + items.push('
Table FILE_READ FILE_WRITE TABLET_LOAD Operations 
', { + html: caption.join('') + }).appendTo('#problemDetails'); + + var items = []; + + items.push('
Table Problem Type Server Time Resource Exception Operations 
Replication ' + + 'table is offline
' + val.tableName + '' + val.peerName + '' + val.remoteIdentifier + '' + val.replicaSystemType + '' + + bigNumberForQuantity(val.filesNeedingReplication) + '
', { + html: caption.join('') + }).appendTo('#replicationStats'); + + var items = []; + + /* + * Adds the columns, add sortTable function on click + */ + items.push('
Table Peer Remote Identifier Replica ' + + 'System Type Files ' + + 'needing replication 
Empty
' + val.server + + '' + + val.scanCount + '' + + timeDuration(val.oldestScan) + '
', { + html: caption.join('') + }).appendTo('#scanStatus'); + + var items = []; + + items.push('
Server Oldest Age