http://git-wip-us.apache.org/repos/asf/accumulo/blob/680b3a21/server/monitor/src/main/resources/resources/js/server.js ---------------------------------------------------------------------- diff --git a/server/monitor/src/main/resources/resources/js/server.js b/server/monitor/src/main/resources/resources/js/server.js new file mode 100644 index 0000000..cd82a54 --- /dev/null +++ b/server/monitor/src/main/resources/resources/js/server.js @@ -0,0 +1,412 @@ +/* +* 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 serv; +/** + * Makes the REST calls, generates the tables with the new information + */ +function refreshServer() { + $.ajaxSetup({ + async: false + }); + getTServer(serv); + $.ajaxSetup({ + async: true + }); + refreshDetailTable(); + refreshHistoryTable(); + refreshCurrentTable(); + refreshResultsTable(); +} + +/** + * Used to redraw the page + */ +function refresh() { + refreshServer(); +} + +/** + * Generates the server details table + */ +function refreshDetailTable() { + + $('#tServerDetail tr:gt(0)').remove(); + + var data = sessionStorage.server === undefined ? + [] : JSON.parse(sessionStorage.server); + + var items = []; + + if (data.length === 0 || data.details === undefined) { + items.push(createEmptyRow(5, 'Empty')); + } else { + items.push(createFirstCell(data.details.hostedTablets, + bigNumberForQuantity(data.details.hostedTablets))); + + items.push(createRightCell(data.details.entries, + bigNumberForQuantity(data.details.entries))); + + items.push(createRightCell(data.details.minors, + bigNumberForQuantity(data.details.minors))); + + items.push(createRightCell(data.details.majors, + bigNumberForQuantity(data.details.majors))); + + items.push(createRightCell(data.details.splits, + bigNumberForQuantity(data.details.splits))); + } + + $('<tr/>', { + html: items.join('') + }).appendTo('#tServerDetail'); +} + +/** + * Generates the server history table + */ +function refreshHistoryTable() { + + $('#opHistoryDetails tr:gt(0)').remove(); + + var data = sessionStorage.server === undefined ? + [] : JSON.parse(sessionStorage.server); + + if (data.length === 0 || data.allTimeTabletResults === undefined) { + var row = []; + + row.push(createEmptyRow(8, 'Empty')); + + $('<tr/>', { + html: row.join('') + }).appendTo('#opHistoryDetails'); + } else { + var totalTimeSpent = 0; + $.each(data.allTimeTabletResults, function(key, val) { + totalTimeSpent += val.timeSpent; + }); + + var count = 0; + $.each(data.allTimeTabletResults, function(key, val) { + var row = []; + + row.push(createFirstCell(val.operation, val.operation)); + + row.push(createRightCell(val.success, bigNumberForQuantity(val.success))); + + row.push(createRightCell(val.failure, + bigNumberForQuantity(val.failure))); + + row.push(createRightCell((val.avgQueueTime == null ? + '-' : val.avgQueueTime * 1000.0), + (val.avgQueueTime == null ? + '—' : timeDuration(val.avgQueueTime * 1000.0)))); + + row.push(createRightCell((val.queueStdDev == null ? + '-' : val.queueStdDev * 1000.0), + (val.queueStdDev == null ? + '—' : timeDuration(val.queueStdDev * 1000.0)))); + + row.push(createRightCell((val.avgTime == null ? + '-' : val.avgTime * 1000.0), + (val.avgTime == null ? + '—' : timeDuration(val.avgTime * 1000.0)))); + + row.push(createRightCell((val.stdDev == null ? + '-' : val.stdDev * 1000.0), + (val.stdDev == null ? + '—' : timeDuration(val.stdDev * 1000.0)))); + + row.push(createRightCell(((val.timeSpent / totalTimeSpent) * 100), + '<div class="progress"><div class="progress-bar"' + + ' role="progressbar" style="min-width: 2em; width:' + + Math.floor((val.timeSpent / totalTimeSpent) * 100) + + '%;">' + Math.floor((val.timeSpent / totalTimeSpent) * 100) + + '%</div></div>')); + + $('<tr/>', { + html: row.join('') + }).appendTo('#opHistoryDetails'); + + }); + } +} + +/** + * Generates the current server table + */ +function refreshCurrentTable() { + + $('#currentTabletOps tr:gt(0)').remove(); + + var data = sessionStorage.server === undefined ? + [] : JSON.parse(sessionStorage.server); + + var items = []; + if (data.length === 0 || data.currentTabletOperationResults === undefined) { + items.push(createEmptyRow(4, 'Empty')); + } else { + var current = data.currentTabletOperationResults; + + items.push(createFirstCell((current.currentMinorAvg == null ? + '-' : current.currentMinorAvg * 1000.0), + (current.currentMinorAvg == null ? + '—' : timeDuration(current.currentMinorAvg * 1000.0)))); + + items.push(createRightCell((current.currentMinorStdDev == null ? + '-' : current.currentMinorStdDev * 1000.0), + (current.currentMinorStdDev == null ? + '—' : timeDuration(current.currentMinorStdDev * 1000.0)))); + + items.push(createRightCell((current.currentMajorAvg == null ? + '-' : current.currentMajorAvg * 1000.0), + (current.currentMajorAvg == null ? + '—' : timeDuration(current.currentMajorAvg * 1000.0)))); + + items.push(createRightCell((current.currentMajorStdDev == null ? + '-' : current.currentMajorStdDev * 1000.0), + (current.currentMajorStdDev == null ? + '—' : timeDuration(current.currentMajorStdDev * 1000.0)))); + } + + $('<tr/>', { + html: items.join('') + }).appendTo('#currentTabletOps'); + +} + +/** + * Generates the server results table + */ +function refreshResultsTable() { + + $('#perTabletResults tr:gt(0)').remove(); + + var data = sessionStorage.server === undefined ? + [] : JSON.parse(sessionStorage.server); + + if (data.length === 0 || data.currentOperations === undefined) { + var row = []; + + row.push(createEmptyRow(11, 'Empty')); + + $('<tr/>', { + html: row.join('') + }).appendTo('#perTabletResults'); + } else { + $.each(data.currentOperations, function(key, val) { + var row = []; + + row.push(createFirstCell(val.name, + '<a href="/tables/' + val.tableID + '">' + val.name + '</a>')); + + row.push(createLeftCell(val.tablet, '<code>' + val.tablet + '</code>')); + + row.push(createRightCell((val.entries == null ? 0 : val.entries), + bigNumberForQuantity(val.entries))); + + row.push(createRightCell((val.ingest == null ? 0 : val.ingest), + bigNumberForQuantity(Math.floor(val.ingest)))); + + row.push(createRightCell((val.query == null ? 0 : val.query), + bigNumberForQuantity(Math.floor(val.query)))); + + row.push(createRightCell((val.minorAvg == null ? + '-' : val.minorAvg * 1000.0), + (val.minorAvg == null ? + '—' : timeDuration(val.minorAvg * 1000.0)))); + + row.push(createRightCell((val.minorStdDev == null ? + '-' : val.minorStdDev * 1000.0), + (val.minorStdDev == null ? + '—' : timeDuration(val.minorStdDev * 1000.0)))); + + row.push(createRightCell((val.minorAvgES == null ? 0 : val.minorAvgES), + bigNumberForQuantity(Math.floor(val.minorAvgES)))); + + row.push(createRightCell((val.majorAvg == null ? + '-' : val.majorAvg * 1000.0), + (val.majorAvg == null ? + '—' : timeDuration(val.majorAvg * 1000.0)))); + + row.push(createRightCell((val.majorStdDev == null ? + '-' : val.majorStdDev * 1000.0), + (val.majorStdDev == null ? + '—' : timeDuration(val.majorStdDev * 1000.0)))); + + row.push(createRightCell((val.majorAvgES == null ? + 0 : val.majorAvgES), + bigNumberForQuantity(Math.floor(val.majorAvgES)))); + + $('<tr/>', { + html: row.join('') + }).appendTo('#perTabletResults'); + }); + } +} + +/** + * Sorts the different server status tables on the selected column + * + * @param {string} table Table ID to sort + * @param {number} n Column number to sort by + */ +function sortTable(table, n) { + var tableIDs = ['tServerDetail', 'opHistoryDetails', + 'currentTabletOps', 'perTabletResults']; + + 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.tableColumn = tableIDs[table]; + sessionStorage.tableColumnSort = n; + + sortTables(tableIDs[table], direction, n); +} + +/** + * Creates the server detail header + * + * @param {string} server Server name + */ +function createDetailHeader(server) { + var caption = []; + serv = server; + + caption.push('<span class="table-caption">Details</span><br>'); + caption.push('<span class="table-subcaption">' + server + '</span><br>'); + + $('<caption/>', { + html: caption.join('') + }).appendTo('#tServerDetail'); + + var items = []; + + var columns = ['Hosted Tablets ', 'Entries ', + 'Minor Compacting ', 'Major Compacting ', + 'Splitting ']; + + for (i = 0; i < columns.length; i++) { + var first = i == 0 ? true : false; + items.push(createHeaderCell(first, 'sortTable(0,' + i + ')', + '', columns[i])); + } + + $('<tr/>', { + html: items.join('') + }).appendTo('#tServerDetail'); +} + +/** + * Creates the server history header + */ +function createHistoryHeader() { + var caption = []; + + caption.push('<span class="table-caption">All-Time Tablet ' + + 'Operation Results</span><br>'); + + $('<caption/>', { + html: caption.join('') + }).appendTo('#opHistoryDetails'); + + var items = []; + + var columns = ['Operation ', 'Success ', 'Failure ', + 'Average<br>Queue Time ', + 'Std. Dev.<br>Queue Time ', + 'Average<br>Time ', 'Std. Dev.<br>Time ', + 'Percentage Time Spent ']; + + for (i = 0; i < columns.length; i++) { + var first = i == 0 ? true : false; + items.push(createHeaderCell(first, 'sortTable(1,' + i + ')', + '', columns[i])); + } + + $('<tr/>', { + html: items.join('') + }).appendTo('#opHistoryDetails'); +} + +/** + * Creates the current server header + */ +function createCurrentHeader() { + var caption = []; + + caption.push('<span class="table-caption">Current Tablet ' + + 'Operation Results</span><br>'); + + $('<caption/>', { + html: caption.join('') + }).appendTo('#currentTabletOps'); + + var items = []; + + var columns = ['Minor Average ', 'Minor Std Dev ', + 'Major Avg ', 'Major Std Dev ']; + + for (i = 0; i < columns.length; i++) { + var first = i == 0 ? true : false; + items.push(createHeaderCell(first, 'sortTable(2,' + i + ')', + '', columns[i])); + } + + $('<tr/>', { + html: items.join('') + }).appendTo('#currentTabletOps'); +} + +/** + * Creates the server result header + */ +function createResultsHeader() { + var caption = []; + + caption.push('<span class="table-caption">Detailed Current ' + + 'Operations</span><br>'); + caption.push('<span class="table-subcaption">Per-tablet ' + + 'Details</span><br>'); + + $('<caption/>', { + html: caption.join('') + }).appendTo('#perTabletResults'); + + var items = []; + + var columns = ['Table ', 'Tablet ', 'Entries ', + 'Ingest ', 'Query ', 'Minor Avg ', + 'Minor Std Dev ', 'Minor Avg e/s ', + 'Major Avg ', 'Major Std Dev ', + 'Major Avg e/s ']; + + for (i = 0; i < columns.length; i++) { + var first = i == 0 ? true : false; + items.push(createHeaderCell(first, 'sortTable(3,' + i + ')', + '', columns[i])); + } + + $('<tr/>', { + html: items.join('') + }).appendTo('#perTabletResults'); +}
http://git-wip-us.apache.org/repos/asf/accumulo/blob/680b3a21/server/monitor/src/main/resources/resources/js/show.js ---------------------------------------------------------------------- diff --git a/server/monitor/src/main/resources/resources/js/show.js b/server/monitor/src/main/resources/resources/js/show.js new file mode 100644 index 0000000..3a8b3ca --- /dev/null +++ b/server/monitor/src/main/resources/resources/js/show.js @@ -0,0 +1,158 @@ +/* +* 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 id; +/** + * Makes the REST calls, generates the tables with the new information + */ +function refreshTraceShow() { + $.ajaxSetup({ + async: false + }); + getTraceShow(id); + $.ajaxSetup({ + async: true + }); + refreshTraceShowTable(); +} + +/** + * Used to redraw the page + */ +function refresh() { + refreshTraceShow(); +} + +/** + * Generates the trace show table + */ +function refreshTraceShowTable() { + clearTable('trace'); + $('#trace caption span span').remove(); + var data = sessionStorage.traceShow === undefined ? + [] : JSON.parse(sessionStorage.traceShow); + + if (data.traces.length !== 0) { + var date = new Date(data.start); + $('#caption').append('<span>' + date.toLocaleString() + '</span>'); + + $.each(data.traces, function(key, val) { + var id = val.spanID.toString(16); + var items = []; + + items.push('<tr>'); + items.push(createRightCell('', val.time + '+')); + items.push(createLeftCell('', val.start)); + items.push('<td style="text-indent: ' + val.level + '0px">' + + val.location + '</td>'); + items.push(createLeftCell('', val.name)); + + if (val.addlData.data.length !== 0 || + val.addlData.annotations.length !== 0) { + + items.push('<td><input type="checkbox" id="' + id + + '_checkbox" onclick="toggle(\'' + id + '\')"></td>'); + items.push('</tr>'); + items.push('<tr id="' + id + '" style="display:none">'); + items.push('<td colspan="5">'); + items.push('<table class="table table-bordered table-striped' + + ' table-condensed">'); + + if (val.addlData.data.length !== 0) { + items.push('<tr><th>Key</th><th>Value</th></tr>'); + + $.each(val.addlData.data, function(key2, val2) { + items.push('<tr><td>' + val2.key + '</td><td>' + val2.value + + '</td></tr>'); + }); + } + + if (val.addlData.annotations.length !== 0) { + items.push('<tr><th>Annotation</th><th>Time Offset</th></tr>'); + + $.each(val.addlData.annotations, function(key2, val2) { + items.push('<tr><td>' + val2.annotation + '</td><td>' + val2.time + + '</td></tr>'); + }); + } + + items.push('</table>'); + items.push('</td>'); + } else { + items.push('<td></td>'); + } + + items.push('</tr>'); + + $('#trace').append(items.join('')); + }); + } else { + var items = []; + items.push('<tr>'); + items.push(createEmptyRow(5, 'No trace information for ID ' + id)); + items.push('</tr>'); + $('#trace').append(items.join('')); + } + +} + +/** + * 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); +} + +/** + * Creates the trace show header + * + * @param {string} ID ID of the trace + */ +function createHeader(ID) { + id = ID; + var caption = []; + + caption.push('<span id="caption" class="table-caption">Trace ' + id + + ' started at<br></span>'); + + $('<caption/>', { + html: caption.join('') + }).appendTo('#trace'); + + var items = []; + + var columns = ['Time ', 'Start ', 'Service@Location ', + 'Name ', 'Addl Data ']; + + for (i = 0; i < columns.length; i++) { + items.push(createHeaderCell(false, '', '', columns[i])); + } + + $('<tr/>', { + html: items.join('') + }).appendTo('#trace'); +} http://git-wip-us.apache.org/repos/asf/accumulo/blob/680b3a21/server/monitor/src/main/resources/resources/js/summary.js ---------------------------------------------------------------------- diff --git a/server/monitor/src/main/resources/resources/js/summary.js b/server/monitor/src/main/resources/resources/js/summary.js new file mode 100644 index 0000000..e3a963c --- /dev/null +++ b/server/monitor/src/main/resources/resources/js/summary.js @@ -0,0 +1,138 @@ +/* +* 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 minutes; +/** + * Makes the REST calls, generates the tables with the new information + */ +function refreshSummary() { + $.ajaxSetup({ + async: false + }); + getTraceSummary(minutes); + $.ajaxSetup({ + async: true + }); + refreshTraceSummaryTable(minutes); +} + +/** + * Used to redraw the page + */ +function refresh() { + refreshSummary(); +} + +/** + * Generates the trace summary table + * + * @param {string} minutes Minutes to display traces + */ +function refreshTraceSummaryTable(minutes) { + clearTable('traceSummary'); + + var data = sessionStorage.traceSummary === undefined ? + [] : JSON.parse(sessionStorage.traceSummary); + + if (data.length === 0 || data.recentTraces.length === 0) { + var items = []; + items.push(createEmptyRow(6, 'No traces available for the last ' + + minutes + ' minute(s)')); + $('<tr/>', { + html: items.join('') + }).appendTo('#traceSummary'); + } else { + $.each(data.recentTraces, function(key, val) { + + var items = []; + + items.push(createFirstCell('', '<a href="/trace/listType?type=' + + val.type + '&minutes=' + minutes + '">' + val.type + '</a>')); + items.push(createRightCell('', bigNumberForQuantity(val.total))); + items.push(createRightCell('', timeDuration(val.min))); + items.push(createRightCell('', timeDuration(val.max))); + items.push(createRightCell('', timeDuration(val.avg))); + items.push('<td class="left">'); + items.push('<table style="width: 100%;">'); + items.push('<tr>'); + + $.each(val.histogram, function(key2, val2) { + items.push('<td style="width:5em">' + (val2 == 0 ? '-' : val2) + + '</td>'); + }); + items.push('</tr>'); + items.push('</table>'); + items.push('</td>'); + + $('<tr/>', { + html: items.join('') + }).appendTo('#traceSummary'); + + }); + } +} + +/** + * Sorts the traceSummary 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('traceSummary', direction, n); +} + +/** + * Creates the trace summary header + * + * @param {string} min Minutes to display trace + */ +function createHeader(min) { + minutes = min; + var caption = []; + + caption.push('<span class="table-caption">All Traces</span><br>'); + + $('<caption/>', { + html: caption.join('') + }).appendTo('#traceSummary'); + + var items = []; + + var columns = ['Type ', 'Total ', 'min ', 'max ', + 'avg ', 'Histogram ']; + + var titles = [descriptions['Trace Type'], descriptions['Total Spans'], + descriptions['Short Span'], descriptions['Long Span'], + descriptions['Avg Span'], descriptions['Histogram']]; + + for (i = 0; i < columns.length; i++) { + var first = i == 0 ? true : false; + items.push(createHeaderCell(first, '', titles[i], columns[i])); + } + + $('<tr/>', { + html: items.join('') + }).appendTo('#traceSummary'); +} http://git-wip-us.apache.org/repos/asf/accumulo/blob/680b3a21/server/monitor/src/main/resources/resources/js/table.js ---------------------------------------------------------------------- diff --git a/server/monitor/src/main/resources/resources/js/table.js b/server/monitor/src/main/resources/resources/js/table.js new file mode 100644 index 0000000..4923208 --- /dev/null +++ b/server/monitor/src/main/resources/resources/js/table.js @@ -0,0 +1,177 @@ +/* +* 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 tableID; +/** + * Makes the REST calls, generates the tables with the new information + */ +function refreshTable() { + $.ajaxSetup({ + async: false + }); + getTableServers(tableID); + $.ajaxSetup({ + async: true + }); + refreshTableServersTable(); +} + +/** + * Used to redraw the page + */ +function refresh() { + refreshTable(); +} + +/** + * Generates the table servers table + */ +function refreshTableServersTable() { + $('#participatingTServers tr:gt(0)').remove(); + + var data = sessionStorage.tableServers === undefined ? + [] : JSON.parse(sessionStorage.tableServers); + + if (data.length === 0 || data.servers.length === 0) { + var items = []; + items.push(createEmptyRow(13, 'Empty')); + $('<tr/>', { + html: items.join('') + }).appendTo('#participatingTServers'); + } else { + + $.each(data.servers, function(key, val) { + var items = []; + items.push(createFirstCell(val.hostname, '<a href="/tservers?s=' + + val.id + '">' + val.hostname + '</a>')); + + items.push(createRightCell(val.tablets, + bigNumberForQuantity(val.tablets))); + + items.push(createRightCell(val.lastContact, + timeDuration(val.lastContact))); + + items.push(createRightCell(val.entries, + bigNumberForQuantity(val.entries))); + + items.push(createRightCell(val.ingest, + bigNumberForQuantity(Math.floor(val.ingest)))); + + items.push(createRightCell(val.query, + bigNumberForQuantity(Math.floor(val.query)))); + + items.push(createRightCell(val.holdtime, + timeDuration(val.holdtime))); + + items.push(createRightCell((val.compactions.scans.running + + val.compactions.scans.queued), + bigNumberForQuantity(val.compactions.scans.running) + + ' (' + bigNumberForQuantity(val.compactions.scans.queued) + + ')')); + + items.push(createRightCell((val.compactions.minor.running + + val.compactions.minor.queued), + bigNumberForQuantity(val.compactions.minor.running) + + ' (' + bigNumberForQuantity(val.compactions.minor.queued) + + ')')); + + items.push(createRightCell((val.compactions.major.running + + val.compactions.major.queued), + bigNumberForQuantity(val.compactions.major.running) + + ' (' + bigNumberForQuantity(val.compactions.major.queued) + + ')')); + + items.push(createRightCell(val.indexCacheHitRate * 100, + Math.round(val.indexCacheHitRate * 100) + '%')); + + items.push(createRightCell(val.dataCacheHitRate * 100, + Math.round(val.dataCacheHitRate * 100) + '%')); + + items.push(createRightCell(val.osload, + bigNumberForQuantity(val.osload))); + + $('<tr/>', { + html: items.join('') + }).appendTo('#participatingTServers'); + + }); + } +} + +/** + * Sorts the participatingTServers table on the selected column + * + * @param {number} n Column number to sort by + */ +function sortTable(n) { + if (!JSON.parse(sessionStorage.namespaceChanged)) { + 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('participatingTServers', direction, n); +} + +/** + * Creates the table servers header + * + * @param {string} table Table Name + * @param {string} tabID Table ID + */ +function createHeader(table, tabID) { + tableID = tabID; + var caption = []; + + caption.push('<span class="table-caption">Participating ' + + 'Tablet Servers</span><br>'); + caption.push('<span class="table-subcaption">' + table + '</span><br>'); + + $('<caption/>', { + html: caption.join('') + }).appendTo('#participatingTServers'); + + var items = []; + + var columns = ['Server ', 'Hosted Tablets ', + 'Last Contact ', 'Entries ', 'Ingest ', + 'Query ', 'Hold Time ', 'Running<br>Scans ', + 'Minor<br>Compactions ', 'Major<br>Compactions ', + 'Index Cache<br>Hit Rate ', 'Data Cache<br>Hit Rate ', + 'OS Load ']; + + var titles = ['', '', '', descriptions['Entries'], descriptions['Ingest'], + descriptions['Query'], descriptions['Hold Time'], + descriptions['Running Scans'], descriptions['Minor Compactions'], + descriptions['Major Compactions'], descriptions['Index Cache Hit Rate'], + descriptions['Data Cache Hit Rate'], descriptions['OS Load']]; + + for (i = 0; i < columns.length; i++) { + var first = i == 0 ? true : false; + items.push(createHeaderCell(first, 'sortTable(' + i + ')', + titles[i], columns[i])); + } + + $('<tr/>', { + html: items.join('') + }).appendTo('#participatingTServers'); +} http://git-wip-us.apache.org/repos/asf/accumulo/blob/680b3a21/server/monitor/src/main/resources/resources/js/tables.js ---------------------------------------------------------------------- diff --git a/server/monitor/src/main/resources/resources/js/tables.js b/server/monitor/src/main/resources/resources/js/tables.js new file mode 100644 index 0000000..3aa1c24 --- /dev/null +++ b/server/monitor/src/main/resources/resources/js/tables.js @@ -0,0 +1,333 @@ +/* +* 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 refreshTables() { + $.ajaxSetup({ + async: false + }); + getNamespaces(); + $.ajaxSetup({ + async: true + }); + createNamespacesDropdown(); + // If the namespaces in sessionStorage is undefined, select all namespaces + if (sessionStorage.namespaces === undefined) { + sessionStorage.namespaces = '[]'; + populateTable('*'); + } + populateTable(undefined); + sortTable(sessionStorage.tableColumnSort === undefined ? + 0 : sessionStorage.tableColumnSort); +} + +/** + * Used to redraw the page + */ +function refresh() { + // If tables are in master page, refresh master and tables + if (!hasMaster) { + refreshTables(); + } else { + refreshMaster(); + refreshTables(); + } +} + +var hasMaster = false; +function toggleMaster(master) { + hasMaster = master +} + +/** + * Creates listeners for when the namespaces are selected or unselected + */ +function namespaceChanged() { + var $namespaceSelect = $('#namespaces'); + + $namespaceSelect.off(); + + $namespaceSelect.on('select2:select', function(e) { + var id = e.params === null ? undefined : e.params['data']['id']; + populateTable(id); + }); + + $namespaceSelect.on('select2:unselect', function(e) { + var id = e.params === null ? undefined : e.params['data']['id']; + populateTable(id); + }); +} + +/** + * Creates the namespaces dropdown menu + */ +function createNamespacesDropdown() { + var data = JSON.parse(NAMESPACES).namespaces; + var caption = []; + + caption.push('<span class="table-caption">Table List</span><br>'); + + $('<caption/>', { + html: caption.join('') + }).appendTo('#filters'); + + var data2 = [{ id: '*', text: '* (All Tables)'}]; + $.each(data, function(key, val) { + var namespace = val === '' ? '- (DEFAULT)' : val; + data2.push({id: val === '' ? '-' : val, text: namespace}); + }); + + $('#namespaces').select2({ + data: data2, + allowClear: true + }); + namespaceChanged(); +} + +/** + * Creates the tables table with the selected namespace + * + * @param {string} ns Selected namespace + */ +function populateTable(ns) { + var tmpArr = sessionStorage.namespaces === undefined ? + [] : JSON.parse(sessionStorage.namespaces); + sessionStorage.namespaceChanged = true; + var namespaces = JSON.parse(NAMESPACES).namespaces; + + // If there is a selected namespace, change the displayed tables + if (ns !== undefined) { + /* + * If the namespace has not been selected, + * add it to the namespace array, otherwise remove it + */ + if (tmpArr.indexOf(ns) == -1) { + /* If the namespace is *, add all namespaces to the array, + * otherwise just add the selected namespace + */ + if (ns === '*') { + tmpArr = []; + + tmpArr.push('*'); + $.each(namespaces, function(key, val) { + tmpArr.push(val === '' ? '-' : val); + }); + } else { + tmpArr.push(ns); + /* + * If the namespace array is the same size + * as the total number of namespaces, add * + */ + if (tmpArr.length == namespaces.length) { + tmpArr.push('*'); + } + } + } else { + /* + * If * is in the array, and the selected + * namespace is not *, remove * from array + */ + if (tmpArr.indexOf('*') !== -1 && ns !== '*') { + tmpArr.splice(tmpArr.indexOf('*'), 1); + } + /* + * If the selected namespace is not *, + * remove it from array, otherwise, remove all + */ + if (ns !== '*') { + tmpArr.splice(tmpArr.indexOf(ns), 1); + } else { + tmpArr = []; + } + } + } + + $('#namespaces').select2().val(tmpArr).trigger('change'); // TODO Fix this, causes null dataAdapter + + sessionStorage.namespaces = JSON.stringify(tmpArr); + + $.ajaxSetup({ + async: false + }); + getNamespaceTables(tmpArr); + $.ajaxSetup({ + async: true + }); + + var data = sessionStorage.tables === undefined ? + [] : JSON.parse(sessionStorage.tables); + clearTable('tableList'); + + var numTables = 0; + + $.each(data.tables, function(keyT, tab) { + // Only add tables that are part of the array, or all if * is in the array + if (tmpArr.indexOf(tab.namespace === '' ? '-' : tab.namespace) !== -1 || + tmpArr.indexOf('*') !== -1) { + $.each(tab.table, function(key, val) { + + var row = []; + row.push(createFirstCell(val.tablename, + '<a href="/tables/' + val.tableId + '">' + val.tablename + '</a>')); + + row.push(createCenterCell(val.tableState, + '<span>' + val.tableState + '</span>')); + + if (val.tableState === 'ONLINE') { + row.push(createRightCell(val.tablets, + bigNumberForQuantity(val.tablets))); + + row.push(createRightCell(val.offlineTablets, + bigNumberForQuantity(val.offlineTablets))); + + row.push(createRightCell(val.recs, + bigNumberForQuantity(val.recs))); + + row.push(createRightCell(val.recsInMemory, + bigNumberForQuantity(val.recsInMemory))); + + row.push(createRightCell(val.ingest, + bigNumberForQuantity(Math.floor(val.ingest)))); + + row.push(createRightCell(val.entriesRead, + bigNumberForQuantity(Math.floor(val.entriesRead)))); + + row.push(createRightCell(val.entriesReturned, + bigNumberForQuantity(Math.floor(val.entriesReturned)))); + + row.push(createRightCell(val.holdTime, + timeDuration(val.holdTime))); + + if (val.scans === null) { + row.push(createRightCell('-', '-')); + } else { + row.push(createRightCell((val.scans.running + val.scans.queued), + bigNumberForQuantity(val.scans.running) + ' (' + + bigNumberForQuantity(val.scans.queued) + ')')); + } + if (val.minorCompactions === null) { + row.push(createRightCell('-', '-')); + } else { + row.push(createRightCell((val.minorCompactions.running + + val.minorCompactions.queued), + bigNumberForQuantity(val.minorCompactions.running) + + ' (' + bigNumberForQuantity(val.minorCompactions.queued) + + ')')); + } + if (val.majorCompactions === null) { + row.push(createRightCell('-', '-')); + } else { + row.push(createRightCell((val.majorCompactions.running + + val.majorCompactions.queued), + bigNumberForQuantity(val.majorCompactions.running) + + ' (' + bigNumberForQuantity(val.majorCompactions.queued) + + ')')); + } + } else { + row.push(createRightCell('-', '-')); + row.push(createRightCell('-', '-')); + row.push(createRightCell('-', '-')); + row.push(createRightCell('-', '-')); + row.push(createRightCell('-', '-')); + row.push(createRightCell('-', '-')); + row.push(createRightCell('-', '-')); + row.push(createRightCell('-', '—')); + row.push(createRightCell('-', '-')); + row.push(createRightCell('-', '-')); + row.push(createRightCell('-', '-')); + } + + $('<tr/>', { + html: row.join(''), + id: tab.namespace === '' ? '-' : tab.namespace + }).appendTo('#tableList'); + + numTables++; + }); + } + }); + /* + * If there are no selected namespaces, + * or selected namespaces result in no tables, display empty + */ + if (numTables === 0) { + var item = createEmptyRow(13, 'Empty'); + + $('<tr/>', { + html: item + }).appendTo('#tableList'); + } +} + +/** + * Sorts the tableList table on the selected column + * + * @param {number} n Column number to sort by + */ +function sortTable(n) { + if (!JSON.parse(sessionStorage.namespaceChanged)) { + if (sessionStorage.tableColumnSort !== undefined && + sessionStorage.tableColumnSort == n && + sessionStorage.direction !== undefined) { + direction = sessionStorage.direction === 'asc' ? 'desc' : 'asc'; + } else { + direction = sessionStorage.direction === undefined ? + 'asc' : sessionStorage.direction; + } + } else { + direction = sessionStorage.direction === undefined ? + 'asc' : sessionStorage.direction; + } + + sessionStorage.tableColumnSort = n; + + sortTables('tableList', direction, n); + sessionStorage.namespaceChanged = false; +} + +/** + * Creates the tables header + */ +function createTablesHeader() { + var items = []; + + var columns = ['Table Name ', 'State ', '# Tablets ', + '# Offline<br>Tablets ', 'Entries ', + 'Entries<br>In Memory ', 'Ingest ', + 'Entries<br>Read ', 'Entries<br>Returned ', + 'Hold Time ', 'Running<br>Scans ', + 'Minor<br>Compactions ', 'Major<br>Compactions ']; + + var titles = ['', '', descriptions['# Tablets'], + descriptions['# Offline Tablets'], descriptions['Entries'], + descriptions['Entries in Memory'], descriptions['Ingest'], + descriptions['Entries Read'], descriptions['Entries Returned'], + descriptions['Hold Time'], descriptions['Running Scans'], + descriptions['Minor Compactions'], descriptions['Major Compactions']]; + + for (i = 0; i < columns.length; i++) { + var first = i == 0 ? true : false; + items.push(createHeaderCell(first, 'sortTable(' + i + ')', + titles[i], columns[i])); + } + + $('<tr/>', { + html: items.join('') + }).appendTo('#tableList'); +} http://git-wip-us.apache.org/repos/asf/accumulo/blob/680b3a21/server/monitor/src/main/resources/resources/js/tservers.js ---------------------------------------------------------------------- diff --git a/server/monitor/src/main/resources/resources/js/tservers.js b/server/monitor/src/main/resources/resources/js/tservers.js new file mode 100644 index 0000000..4c7ac20 --- /dev/null +++ b/server/monitor/src/main/resources/resources/js/tservers.js @@ -0,0 +1,314 @@ +/* +* 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 tservers initial table + */ +$(document).ready(function() { + createHeader(); + refreshTServers(); + + // Create tooltip for table column information + $(document).tooltip(); +}); + +/** + * Makes the REST calls, generates the tables with the new information + */ +function refreshTServers() { + $.ajaxSetup({ + async: false + }); + getTServers(); + $.ajaxSetup({ + async: true + }); + refreshBadTServersTable(); + refreshDeadTServersTable(); + refreshTServersTable(); +} + +/** + * Used to redraw the page + */ +function refresh() { + refreshTServers(); +} + +/** + * Generates the tservers table + */ +function refreshBadTServersTable() { + var data = sessionStorage.tservers === undefined ? + [] : JSON.parse(sessionStorage.tservers); + + $('#badtservers tr').remove(); + $('#badtservers caption').remove(); + + if (data.length === 0 || data.badServers.length === 0) { + + $('#badtservers').hide(); + } else { + + $('#badtservers').show(); + + var caption = []; + + caption.push('<span class="table-caption">Non-Functioning ' + + 'Tablet Servers</span><br>'); + caption.push('<span class="table-subcaption">The following tablet' + + ' servers reported a status other than Online</span><br>'); + + $('<caption/>', { + html: caption.join('') + }).appendTo('#badtservers'); + + var items = []; + + var columns = ['Tablet Server ', + 'Tablet Server Status ']; + + for (i = 0; i < columns.length; i++) { + var first = i == 0 ? true : false; + items.push(createHeaderCell(first, 'sortTable(0,' + i + ')', + '', columns[i])); + } + + $('<tr/>', { + html: items.join('') + }).appendTo('#badtservers'); + + $.each(data.badServers, function(key, val) { + var items = []; + items.push(createFirstCell(val.id, val.id)); + items.push(createRightCell(val.status, val.status)); + + $('<tr/>', { + html: items.join('') + }).appendTo('#badtservers'); + }); + } +} + +/** + * Generates the deadtservers table + */ +function refreshDeadTServersTable() { + var data = sessionStorage.tservers === undefined ? + [] : JSON.parse(sessionStorage.tservers); + + $('#deadtservers tr').remove(); + $('#deadtservers caption').remove(); + + if (data.length === 0 || data.deadServers.length === 0) { + + $('#deadtservers').hide(); + } else { + + $('#deadtservers').show(); + + + var caption = []; + + caption.push('<span class="table-caption">Dead ' + + 'Tablet Servers</span><br>'); + caption.push('<span class="table-subcaption">The following' + + ' tablet servers are no longer reachable.</span><br>'); + + $('<caption/>', { + html: caption.join('') + }).appendTo('#deadtservers'); + + var items = []; + + var columns = ['Server ', 'Last Updated ', 'Event ', + 'Clear']; + + for (i = 0; i < columns.length; i++) { + var first = i == 0 ? true : false; + var sort = i == columns.length - 1 ? '' : 'sortTable(1,' + i + ')'; + items.push(createHeaderCell(first, sort, '', columns[i])); + } + + $('<tr/>', { + html: items.join('') + }).appendTo('#deadtservers'); + + $.each(data.deadServers, function(key, val) { + var items = []; + items.push(createFirstCell(val.server, val.server)); + + var date = new Date(val.lastStatus); + date = date.toLocaleString().split(' ').join(' '); + items.push(createRightCell(val.lastStatus, date)); + items.push(createRightCell(val.status, val.status)); + items.push(createRightCell('', '<a href="javascript:clearDeadTServers(\'' + + val.server + '\');">clear</a>')); + + $('<tr/>', { + html: items.join('') + }).appendTo('#deadtservers'); + }); + } +} + +/** + * Makes the REST POST call to clear dead table server + * + * @param {string} server Dead TServer to clear + */ +function clearDeadTServers(server) { + clearDeadServers(server); + refreshTServers(); + refreshNavBar(); +} + +/** + * Generates the tserver table + */ +function refreshTServersTable() { + var data = sessionStorage.tservers === undefined ? + [] : JSON.parse(sessionStorage.tservers); + + $('#tservers tr:gt(0)').remove(); + + if (data.length === 0 || data.servers.length === 0) { + var item = createEmptyRow(13, 'Empty'); + + $('<tr/>', { + html: item + }).appendTo('#tservers'); + } else { + + $.each(data.servers, function(key, val) { + var items = []; + items.push(createFirstCell(val.hostname, + '<a href="/tservers?s=' + val.id + '">' + val.hostname + '</a>')); + + items.push(createRightCell(val.tablets, + bigNumberForQuantity(val.tablets))); + + items.push(createRightCell(val.lastContact, + timeDuration(val.lastContact))); + + items.push(createRightCell(val.entries, + bigNumberForQuantity(val.entries))); + + items.push(createRightCell(val.ingest, + bigNumberForQuantity(Math.floor(val.ingest)))); + + items.push(createRightCell(val.query, + bigNumberForQuantity(Math.floor(val.query)))); + + items.push(createRightCell(val.holdtime, + timeDuration(val.holdtime))); + + items.push(createRightCell((val.compactions.scans.running + + val.compactions.scans.queued), + bigNumberForQuantity(val.compactions.scans.running) + + ' (' + bigNumberForQuantity(val.compactions.scans.queued) + + ')')); + + items.push(createRightCell((val.compactions.minor.running + + val.compactions.minor.queued), + bigNumberForQuantity(val.compactions.minor.running) + + ' (' + bigNumberForQuantity(val.compactions.minor.queued) + + ')')); + + items.push(createRightCell((val.compactions.major.running + + val.compactions.major.queued), + bigNumberForQuantity(val.compactions.major.running) + + ' (' + bigNumberForQuantity(val.compactions.major.queued) + + ')')); + + items.push(createRightCell(val.indexCacheHitRate * 100, + Math.round(val.indexCacheHitRate * 100) + '%')); + + items.push(createRightCell(val.dataCacheHitRate * 100, + Math.round(val.dataCacheHitRate * 100) + '%')); + + items.push(createRightCell(val.osload, bigNumberForQuantity(val.osload))); + + $('<tr/>', { + html: items.join('') + }).appendTo('#tservers'); + }); + } +} + +/** + * Sorts the tservers table on the selected column + * + * @param {string} table Table ID to sort + * @param {number} n Column number to sort by + */ +function sortTable(table, n) { + var tableIDs = ['badtservers', 'deadtservers', 'tservers']; + + 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.tableColumn = tableIDs[table]; + sessionStorage.tableColumnSort = n; + sortTables(tableIDs[table], direction, n); +} + +/** + * Creates the tservers header + */ +function createHeader() { + var caption = []; + + caption.push('<span class="table-caption">Tablet Servers</span><br>'); + caption.push('<span class="table-subcaption">Click on the ' + + '<span style="color: #0000ff;">server address</span> to ' + + 'view detailed performance statistics for that server.</span><br>'); + + $('<caption/>', { + html: caption.join('') + }).appendTo('#tservers'); + + var items = []; + + var columns = ['Server ', 'Hosted Tablets ', + 'Last Contact ', 'Entries ', 'Ingest ', + 'Query ', 'Hold Time ', 'Running<br>Scans ', + 'Minor<br>Compactions ', 'Major<br>Compactions ', + 'Index Cache<br>Hit Rate ', 'Data Cache<br>Hit Rate ', + 'OS Load ']; + + var titles = ['', '', '', descriptions['Entries'], descriptions['Ingest'], + descriptions['Query'], descriptions['Hold Time'], + descriptions['Running Scans'], descriptions['Minor Compactions'], + descriptions['Major Compactions'], descriptions['Index Cache Hit Rate'], + descriptions['Data Cache Hit Rate'], descriptions['OS Load']]; + + for (i = 0; i < columns.length; i++) { + var first = i == 0 ? true : false; + items.push(createHeaderCell(first, 'sortTable(2,' + i + ')', + titles[i], columns[i])); + } + + $('<tr/>', { + html: items.join('') + }).appendTo('#tservers'); +} http://git-wip-us.apache.org/repos/asf/accumulo/blob/680b3a21/server/monitor/src/main/resources/resources/js/vis.js ---------------------------------------------------------------------- diff --git a/server/monitor/src/main/resources/resources/js/vis.js b/server/monitor/src/main/resources/resources/js/vis.js new file mode 100644 index 0000000..bcf5327 --- /dev/null +++ b/server/monitor/src/main/resources/resources/js/vis.js @@ -0,0 +1,506 @@ +/* + * 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. + */ + +// Server Stats +var statNames = {}, maxStatValues = {}, adjustMax = {}, significance = {}; + +/** + * Sets the options for the server visualization + * + * @param {string} shape Circle or Square + * @param {number} size Size of shape + * @param {string} motion Stat to display motion + * @param {string} color Stat to display color + */ +function setOptions(shape, size, motion, color) { + var data = sessionStorage.serverStats === undefined ? + {} : JSON.parse(sessionStorage.serverStats); + $('#motion').empty(); + $('#color').empty(); + + $.each(data.serverStats, function(key, val) { + var item = val.description; + + $('#motion').append('<option ' + (motion === val.name ? 'selected' : '') + + '>' + item + '</option>'); + $('#color').append('<option ' + (color === val.name ? 'selected' : '') + + '>' + item + '</option>'); + + }); + if (speedStatType === undefined) { + speedStatType = motion !== undefined || motion !== '' ? motion : ''; + speedDisabled = motion !== '' ? false : true; + } + if (speedStatType !== motion && motion !== undefined && + motion !== 'osload' && motion !== '') { + speedStatType = motion; + speedDisabled = false; + } + if (colorStatType === undefined) { + colorStatType = color !== undefined ? color : 'osload'; + } + if (colorStatType !== color && color !== undefined) { + colorStatType = color; + } +} + +/** + * Sets the stats values from the REST call + */ +function setStats() { + + var data = JSON.parse(sessionStorage.serverStats); + + $.each(data.serverStats, function(key, val) { + statNames[val.name] = val.derived; + maxStatValues[val.name] = val.max; + adjustMax[val.name] = val.adjustMax; + significance[val.name] = val.significance; + }); + + var numNormalStats = 8; +} + +// size and spacing variables +var dotSpacing = 10; // spacing between centers of dots (radius) +var dotPadding = 0.5; // dot padding +var minDotRadius = 3; // min dot radius +var maxDotRadius = dotSpacing - dotPadding; + +// arrays of information about each dot +var stats = {'servers': []}; +var dots = new Array(0); // current sizes and change directions +var mousedDot = -1; // the dot currently under the mouse + +var colorPalette = ['#0000CC', '#0014B8', '#0029A3', '#003D8F', '#00527A', + '#006666', '#007A52', '#008F3D', '#00A329', '#00B814', '#00CC00', + '#14D100', '#29D600', '#3DDB00', '#52E000', '#66E600', '#7AEB00', + '#8FF000', '#A3F500', '#B8FA00', '#CCFF00', '#CCFF00', '#CCF200', + '#CCE600', '#CCD900', '#CCCC00', '#CCBF00', '#CCB200', '#CCA600', + '#CC9900', '#CC8C00', '#CC8000', '#CC7300', '#CC6600', '#CC5900', + '#CC4C00', '#CC4000', '#CC3300', '#CC2600', '#CC1A00', '#CC0D00', + '#CC0000']; + +var nullColor = '#F5F8FA'; +var deadColor = '#B000CC'; + +// animation variables +var drawing = false; +var canvas = document.getElementById('visCanvas'); +var context = canvas.getContext('2d'); + +// mouse handling for server information display +document.getElementById('hoverable').addEventListener('mouseover', + showId, false); +document.getElementById('hoverable').addEventListener('mousemove', + showId, false); +document.getElementById('hoverable').addEventListener('mouseout', + hideId, false); +document.getElementById('vishoverinfo').addEventListener('click', + goToServer, false); +canvas.addEventListener('click', goToServer, false); + +// initialize settings based on request parameters +var main = document.getElementById('main'); +var speedStatType; +var colorStatType; +var speedDisabled = true; +var useCircles = true; +setShape(document.getElementById('shape')); +setSize(document.getElementById('size')); +setMotion(document.getElementById('motion')); +setColor(document.getElementById('color')); + +// xml loading variables +var xmlReturned = true; +// don't bother allowing for IE 5 or 6 since canvas won't work +var xmlhttp = new XMLHttpRequest(); +xmlhttp.onreadystatechange = function() { + handleNewData(); +}; + +self.setInterval('getXML()', 5000); + +//self.setInterval('drawDots()',20); + +window.requestAnimFrame = (function(callback) { + return window.requestAnimationFrame || + window.webkitRequestAnimationFrame || + window.mozRequestAnimationFrame || + window.oRequestAnimationFrame || + window.msRequestAnimationFrame || + function(callback) { + window.setTimeout(callback, 1000 / 60); + }; +})(); + +function handleNewData() { + if (xmlhttp.readyState != 4) { + return; + } + if (xmlhttp.status != 200 || xmlhttp.responseText == null) { + xmlReturned = true; + return; + } + var newstats = JSON.parse(xmlhttp.responseText); + for (var i in newstats.servers) { + for (var s in statNames) { + if (statNames[s]) + continue; + newstats.servers[i][s] = Math.max(0, Math.floor(significance[s] * + newstats.servers[i][s]) / significance[s]); + if (adjustMax[s]) + maxStatValues[s] = Math.max(newstats.servers[i][s], maxStatValues[s]); + } + } + + initDerivedInfo(newstats); + var oldstats = stats; + while (drawing) {} + stats = newstats; + delete oldstats; + xmlReturned = true; +} + +// set max and average +function setDerivedStats(serverStats) { + var avgStat = 0; + var maxStat = 0; + var maxIndex = 0; + for (var s in statNames) { + if (statNames[s]) + continue; + normStat = serverStats[s] / maxStatValues[s]; + if (normStat > 0) + avgStat += normStat; + if (maxStat < normStat) { + maxStat = normStat; + maxIndex = s; + } + } + serverStats.allmax = Math.floor(significance.allmax * + Math.min(1, maxStat)) / significance.allmax; + serverStats.allavg = Math.floor(significance.allavg * + avgStat / numNormalStats) / significance.allavg; + serverStats.maxStat = maxIndex; +} + +function initDerivedInfo(newstats) { + for (var i in newstats.servers) { + if ('dead' in newstats.servers[i] || 'bad' in newstats.servers[i]) { + continue; + } + if (i >= dots.length) { + dots.push({'size': maxDotRadius, 'growing': false}); + } + setDerivedStats(newstats.servers[i]); + } +} + +// construct server info for hover +function getInfo(serverStats) { + var extra = '<strong>' + serverStats.ip + '</strong>'; + if ('dead' in serverStats || 'bad' in serverStats) + return extra; + extra = extra + ' (' + serverStats.hostname + ')'; + var j = 0; + for (var s in statNames) { + if (j % 4 == 0) + extra = extra + '<br>\n'; + extra = extra + ' ' + s + ': <strong>' + + serverStats[s] + '</strong>'; + j++; + } + extra = extra + ' (' + serverStats.maxStat + ')'; + return extra; +} + +// reload xml +function getXML() { + if (xmlReturned == true) { + xmlReturned = false; + xmlhttp.open('GET', jsonurl, true); + xmlhttp.send(); + } +} + +// redraw +function drawDots() { + requestAnimFrame(drawDots); + var width = Math.ceil(Math.sqrt(stats.servers.length)); + var height = Math.ceil(stats.servers.length / width); + var x; + var y; + var server; + var sizeChange; + drawing = true; + for (var i in stats.servers) { + server = stats.servers[i]; + x = i % width; + y = Math.floor(i / width); + if ('bad' in server || 'dead' in server) { + strokeDot(x, y, maxDotRadius - 1, deadColor); + continue; + } + if (speedDisabled || Math.floor(dots[i].size) > maxDotRadius) { + // check for resize by the user + dots[i].size = maxDotRadius; + } else if (server[speedStatType] <= 0) { + // if not changing size, increase to max radius + if (dots[i].size < maxDotRadius) + dots[i].size = dots[i].size + 1; + if (dots[i].size > maxDotRadius) + dots[i].size = maxDotRadius; + } else { + sizeChange = getStat(i, speedStatType); + if (dots[i].growing) { + dots[i].size = dots[i].size + sizeChange; + if (dots[i].size + sizeChange > maxDotRadius) { + dots[i].growing = false; + } + } + else { + dots[i].size = dots[i].size - sizeChange; + if (dots[i].size - sizeChange < minDotRadius) { + dots[i].growing = true; + } + } + } + drawDot(x, y, Math.floor(dots[i].size), + getColor(getStat(i, colorStatType))); + } + /* + * mousedDot shouldn't be set to an invalid dot, + * but stats might have changed since then + */ + if (mousedDot >= 0 && mousedDot < stats.servers.length) + document.getElementById('vishoverinfo').innerHTML = + getInfo(stats.servers[mousedDot]); + drawing = false; +} + +// fill in a few grey dots +function drawGrid() { + context.clearRect(0, 0, canvas.width, canvas.height); + for (var i = 0, k = 0; i < canvas.width; i += dotSpacing * 2, k++) { + for (var j = 0, l = 0; j < canvas.height; j += dotSpacing * 2, l++) { + drawDot(k, l, maxDotRadius, nullColor); + } + } +} + +// fill a dot specified by indices into dot grid +function drawDot(i, j, r, c) { + var x = i * dotSpacing * 2 + dotSpacing; + var y = j * dotSpacing * 2 + dotSpacing; + context.clearRect(x - dotSpacing, y - dotSpacing, dotSpacing * 2, + dotSpacing * 2); + if (useCircles) + fillCircle(x, y, r - dotPadding, c); + else + fillSquare(x - r, y - r, (r - dotPadding) * 2, c); +} + +// stroke a dot specified by indices into dot grid +function strokeDot(i, j, r, c) { + var x = i * dotSpacing * 2 + dotSpacing; + var y = j * dotSpacing * 2 + dotSpacing; + context.clearRect(x - dotSpacing, y - dotSpacing, dotSpacing * 2, + dotSpacing * 2); + if (useCircles) + strokeCircle(x, y, r - dotPadding, c); + else + strokeSquare(x - r, y - r, (r - dotPadding) * 2, c); +} + +function getStat(dotIndex, statIndex) { + return Math.min(1, stats.servers[dotIndex][statIndex] / + maxStatValues[statIndex]); +} + +// translate color between 0 and maxObservedColor into an html color code +function getColor(normColor) { + return colorPalette[Math.round((colorPalette.length - 1) * normColor)]; +} + +function strokeCircle(x, y, r, c) { + context.strokeStyle = c; + context.lineWidth = 2; + context.beginPath(); + context.arc(x, y, r, 0, Math.PI * 2, true); + context.closePath(); + context.stroke(); +} + +function fillCircle(x, y, r, c) { + context.fillStyle = c; + context.beginPath(); + context.arc(x, y, r, 0, Math.PI * 2, true); + context.closePath(); + context.fill(); +} + +function strokeSquare(x, y, d, c) { + context.strokeStyle = c; + context.lineWidth = 2; + context.strokeRect(x, y, d, d); +} + +function fillSquare(x, y, d, c) { + context.fillStyle = c; + context.fillRect(x, y, d, d); +} + +// callback for shape selection +function setShape(obj) { + switch (obj.selectedIndex) { + case 0: + useCircles = true; + break; + case 1: + useCircles = false; + break; + default: + useCircles = true; + } + drawGrid(); + setState(); +} + +// callback for size selection +function setSize(obj) { + switch (obj.selectedIndex) { + case 0: + dotSpacing = 5; + minDotRadius = 1; + break; + case 1: + dotSpacing = 10; + minDotRadius = 3; + break; + case 2: + dotSpacing = 20; + minDotRadius = 5; + break; + case 3: + dotSpacing = 40; + minDotRadius = 7; + break; + default: + dotSpacing = 10; + minDotRadius = 3; + } + maxDotRadius = dotSpacing - dotPadding; + drawGrid(); + setState(); +} + +// callback for motion selection +function setMotion(obj) { + if (obj.selectedIndex <= 0) { + speedDisabled = true; + setState(); + return; + } + var i = 0; + for (var s in statNames) { + if (i == obj.selectedIndex) { + speedStatType = s; + break; + } + i++; + } + speedDisabled = false; + setState(); +} + +// callback for color selection +function setColor(obj) { + var i = 0; + for (var s in statNames) { + if (i == obj.selectedIndex) { + colorStatType = s; + break; + } + i++; + } + setState(); +} + +// hide server info on mouseout +function hideId(e) { + document.getElementById('vishoverinfo').style.visibility = 'hidden'; +} + +// display server info on mouseover +function showId(e) { + var x; + var y; + if (e.pageX || e.pageY) { + x = e.pageX + main.scrollLeft; + y = e.pageY + main.scrollTop; + } + else { + // clientX and clientY unimplemented + return; + } + var relx = x - canvas.offsetLeft - main.offsetLeft; + var rely = y - canvas.offsetTop - main.offsetTop; + var width = Math.ceil(Math.sqrt(stats.servers.length)); + gotDot = Math.floor(relx / (dotSpacing * 2)) + width * + Math.floor(rely / (dotSpacing * 2)); + mousedDot = -1; + if (relx < (width * dotSpacing * 2) && gotDot >= 0 && + gotDot < stats.servers.length) { + mousedDot = gotDot; + document.getElementById('vishoverinfo').style.left = relx + + canvas.offsetLeft; + document.getElementById('vishoverinfo').style.top = Math.max(0, + rely + canvas.offsetTop - 70); + document.getElementById('vishoverinfo').style.visibility = 'visible'; + } + else { + document.getElementById('vishoverinfo').style.visibility = 'hidden'; + } +} + +function setState() { + var url = visurl + '?shape=' + (useCircles ? 'circles' : 'squares') + + '&size=' + (dotSpacing * 2) + (speedDisabled ? '' : + '&motion=' + speedStatType) + + '&color=' + colorStatType; + window.history.replaceState(window.history.state, 'Server Activity', url); + + setOptions(useCircles ? 'circles' : 'squares', dotSpacing * 2, + speedDisabled ? '' : speedStatType, colorStatType); +} + +// go to server page on click +function goToServer(e) { + /* + * mousedDot shouldn't be set to an invalid dot, + * but stats might have changed since then + */ + if (mousedDot >= 0 && mousedDot < stats.servers.length) + window.location = serverurl + stats.servers[mousedDot].ip; +} + +/*window.onload = function() { + drawGrid(); + drawDots(); + getXML(); +}*/ http://git-wip-us.apache.org/repos/asf/accumulo/blob/680b3a21/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 deleted file mode 100644 index 8d74645..0000000 --- a/server/monitor/src/main/resources/resources/listType.js +++ /dev/null @@ -1,140 +0,0 @@ -/* -* 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 </th>'); - items.push('<th title="' + descriptions['Span Time'] + '">ms </th>'); - items.push('<th title="' + descriptions['Source'] + '">Source </th>'); - - $('<tr/>', { - html: items.join('') - }).appendTo('#trace'); -} http://git-wip-us.apache.org/repos/asf/accumulo/blob/680b3a21/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 deleted file mode 100644 index 4c5adf9..0000000 --- a/server/monitor/src/main/resources/resources/log.js +++ /dev/null @@ -1,173 +0,0 @@ -/* -* 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(' ') + '</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 ' + - 'All 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 </th>'); - items.push('<th onclick="sortTable(1)">Application </th>'); - items.push('<th onclick="sortTable(2)">Count </th>'); - items.push('<th onclick="sortTable(3)">Level </th>'); - items.push('<th onclick="sortTable(4)">Message </th>'); - - $('<tr/>', { - html: items.join('') - }).appendTo('#logTable'); -} http://git-wip-us.apache.org/repos/asf/accumulo/blob/680b3a21/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 deleted file mode 100644 index a4c4c3e..0000000 --- a/server/monitor/src/main/resources/resources/master.js +++ /dev/null @@ -1,265 +0,0 @@ -/* -* 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 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 </th>'); - items.push('<th onclick="sortTable(1)">Log </th>'); - items.push('<th onclick="sortTable(2)">Time </th>'); - items.push('<th onclick="sortTable(3)">Copy/Sort </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(' '); - 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(' '); - 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 sortMasterTable(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 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="sortMasterTable(0)" title="' + - descriptions['Master'] + '">Master </th>'); - - items.push('<th onclick="sortMasterTable(1)" title="' + - descriptions['# Online Tablet Servers'] + - '"># Online<br />Tablet Servers </th>'); - - items.push('<th onclick="sortMasterTable(2)" title="' + - descriptions['# Total Tablet Servers'] + - '"># Total<br />Tablet Servers </th>'); - - items.push('<th onclick="sortMasterTable(3)" title="' + - descriptions['Last GC'] + '">Last GC </th>'); - - items.push('<th onclick="sortMasterTable(4)" title="' + - descriptions['# Tablets'] + '"># Tablets </th>'); - - items.push('<th onclick="sortMasterTable(5)"># Unassigned' + - '<br />Tablets </th>'); - items.push('<th onclick="sortMasterTable(6)" title="' + - descriptions['Total Entries'] + '">Entries </th>'); - items.push('<th onclick="sortMasterTable(7)" title="' + - descriptions['Total Ingest'] + '">Ingest </th>'); - items.push('<th onclick="sortMasterTable(8)" title="' + - descriptions['Total Entries Read'] + '">Entries<br />Read </th>'); - items.push('<th onclick="sortMasterTable(9)" title="' + - descriptions['Total Entries Returned'] + - '">Entries<br />Returned </th>'); - items.push('<th onclick="sortMasterTable(10)" title="' + - descriptions['Max Hold Time'] + '">Hold Time </th>'); - items.push('<th onclick="sortMasterTable(11)" title="' + - descriptions['OS Load'] + '">OS Load </th>'); - - $('<tr/>', { - html: items.join('') - }).appendTo('#masterStatus'); -}
