Added in the queries page
Project: http://git-wip-us.apache.org/repos/asf/incubator-blur/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-blur/commit/5ccdd5e9 Tree: http://git-wip-us.apache.org/repos/asf/incubator-blur/tree/5ccdd5e9 Diff: http://git-wip-us.apache.org/repos/asf/incubator-blur/diff/5ccdd5e9 Branch: refs/heads/apache-blur-0.2 Commit: 5ccdd5e9e1cb214605d26462e3cfdceadc5128fa Parents: 9f225a1 Author: Chris Rohr <[email protected]> Authored: Sat Mar 29 10:02:52 2014 -0400 Committer: Chris Rohr <[email protected]> Committed: Sat Mar 29 10:02:52 2014 -0400 ---------------------------------------------------------------------- contrib/blur-console/ui/app/index.html | 1 + .../ui/app/scripts/blurconsole.fake.js | 23 +++- .../ui/app/scripts/blurconsole.model.js | 67 ++++++++- .../ui/app/scripts/blurconsole.queries.js | 136 +++++++++++++++++-- .../ui/app/scripts/blurconsole.tables.js | 35 ++++- .../ui/app/styles/blurconsole.queries.scss | 22 +++ .../blur-console/ui/app/views/queries.tpl.html | 22 ++- 7 files changed, 288 insertions(+), 18 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/5ccdd5e9/contrib/blur-console/ui/app/index.html ---------------------------------------------------------------------- diff --git a/contrib/blur-console/ui/app/index.html b/contrib/blur-console/ui/app/index.html index b0f8471..41a33a9 100644 --- a/contrib/blur-console/ui/app/index.html +++ b/contrib/blur-console/ui/app/index.html @@ -39,6 +39,7 @@ under the License. <link rel="stylesheet" href="styles/blurconsole.css"> <link rel="stylesheet" href="styles/blurconsole.dashboard.css"> <link rel="stylesheet" href="styles/blurconsole.schema.css"> + <link rel="stylesheet" href="styles/blurconsole.queries.css"> <!-- endbuild --> <script src="bower_components/modernizr/modernizr.js"></script> http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/5ccdd5e9/contrib/blur-console/ui/app/scripts/blurconsole.fake.js ---------------------------------------------------------------------- diff --git a/contrib/blur-console/ui/app/scripts/blurconsole.fake.js b/contrib/blur-console/ui/app/scripts/blurconsole.fake.js index 81708d5..ebc53e4 100644 --- a/contrib/blur-console/ui/app/scripts/blurconsole.fake.js +++ b/contrib/blur-console/ui/app/scripts/blurconsole.fake.js @@ -20,7 +20,7 @@ under the License. /*global blurconsole:false */ blurconsole.fake = (function() { 'use strict'; - var getTableList, getNodeList, getQueryPerformance, getQueries, disableTable, enableTable, deleteTable, getSchema, findTerms, + var getTableList, getNodeList, getQueryPerformance, getQueries, cancelQuery, disableTable, enableTable, deleteTable, getSchema, findTerms, randomNumber, randomBoolean, randomString; getTableList = function() { @@ -70,12 +70,30 @@ blurconsole.fake = (function() { getQueries = function() { console.log('getting fake queries'); + var queries = []; + + for (var i=0; i < randomNumber(50); i++) { + queries.push({ + uuid: randomString(), + user: 'user_' + randomNumber(10, true), + query: randomString(), + table: 'testtable' + randomNumber(5, true), + state: randomNumber(3, true), + percent: randomNumber(100, true), + startTime: new Date() + }); + } + return { slowQueries : randomNumber(100) % 10 === 0, - + queries : queries }; }; + cancelQuery = function(uuid) { + console.log('Fake sending request to cancel query [' + uuid + ']'); + }; + disableTable = function(table) { console.log('Fake sending request to disable table [' + table + ']'); }; @@ -167,6 +185,7 @@ blurconsole.fake = (function() { getNodeList : getNodeList, getQueryPerformance : getQueryPerformance, getQueries : getQueries, + cancelQuery : cancelQuery, disableTable : disableTable, enableTable : enableTable, deleteTable : deleteTable, http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/5ccdd5e9/contrib/blur-console/ui/app/scripts/blurconsole.model.js ---------------------------------------------------------------------- diff --git a/contrib/blur-console/ui/app/scripts/blurconsole.model.js b/contrib/blur-console/ui/app/scripts/blurconsole.model.js index b6917da..6153bd9 100644 --- a/contrib/blur-console/ui/app/scripts/blurconsole.model.js +++ b/contrib/blur-console/ui/app/scripts/blurconsole.model.js @@ -31,7 +31,7 @@ blurconsole.model = (function() { queries : {} }, isFakeData = true, - tables, metrics, nodes, initModule, nodePoller, tablePoller, queryPerformancePoller, queryPoller; + tables, metrics, nodes, queries, initModule, nodePoller, tablePoller, queryPerformancePoller, queryPoller; tables = (function() { var getClusters, getEnabledTables, getDisabledTables, isDataLoaded, disableTable, enableTable, deleteTable, getSchema, findTerms; @@ -232,7 +232,7 @@ blurconsole.model = (function() { queryData, mean; queryData = stateMap.queryPerformance; - + $.each(queryData, function(idx, increment) { total += increment; }); @@ -278,6 +278,66 @@ blurconsole.model = (function() { }; }()); + queries = (function() { + var queriesForTable, cancelQuery, tableHasActivity, matchesFilter, + states = ['running', 'interrupted', 'complete', 'backpressureinterrupted']; + + queriesForTable = function(table, sort, filter) { + var queries = [], qSort, sortField, sortDir; + + qSort = (sort || 'startTime~desc').split('~'); + sortField = qSort[0]; + sortDir = qSort.length > 1 ? qSort[1] : 'asc'; + + $.each(stateMap.queries.queries, function(i, query){ + if (query.table === table && matchesFilter(query, filter)) { + queries.push(query); + } + }); + + queries.sort(function(a, b){ + if (sortDir === 'asc') { + return a[sortField] > b[sortField]; + } else { + return b[sortField] > b[sortField]; + } + }); + + return queries; + }; + + cancelQuery = function(uuid) { + configMap.poller.cancelQuery(uuid); + }; + + tableHasActivity = function(table) { + var hasActivity = false; + $.each(stateMap.queries.queries, function(i, query){ + if (query.table === table) { + hasActivity = true; + return false; + } + }); + return hasActivity; + }; + + matchesFilter = function(queryData, filterText) { + var queryStr = queryData.user + '~~~' + queryData.query + '~~~' + states[queryData.state]; + + if (filterText === null || filterText === '') { + return true; + } + + return queryStr.toLowerCase().indexOf(filterText.toLowerCase()) !== -1; + }; + + return { + queriesForTable : queriesForTable, + cancelQuery : cancelQuery, + tableHasActivity : tableHasActivity + }; + }()); + nodePoller = function() { var tmpNodeMap = configMap.poller.getNodeList(); if (!blurconsole.utils.equals(tmpNodeMap, stateMap.nodeMap)) { @@ -328,6 +388,7 @@ blurconsole.model = (function() { initModule : initModule, tables : tables, metrics: metrics, - nodes : nodes + nodes : nodes, + queries : queries }; }()); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/5ccdd5e9/contrib/blur-console/ui/app/scripts/blurconsole.queries.js ---------------------------------------------------------------------- diff --git a/contrib/blur-console/ui/app/scripts/blurconsole.queries.js b/contrib/blur-console/ui/app/scripts/blurconsole.queries.js index eba3edf..ce0298c 100644 --- a/contrib/blur-console/ui/app/scripts/blurconsole.queries.js +++ b/contrib/blur-console/ui/app/scripts/blurconsole.queries.js @@ -16,38 +16,158 @@ KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ +/*jshint laxbreak: true */ /*global blurconsole:false */ blurconsole.queries = (function () { 'use strict'; var configMap = { - view : 'views/queries.tpl.html' + view : 'views/queries.tpl.html', + states : ['Running', 'Interrupted', 'Complete', 'Back Pressure Interrupted'], + queryDef : [ + {label:'User', key:'user'}, + {label:'Query', key: 'query'}, + {label:'Time Started', key: 'startTime'}, + {label:'State', key: function(row) { + var stateInfo = configMap.states[row.state]; + + if (row.state === 0) { + stateInfo += ' <div class="badge badge-info">' + row.percent + '%</div>'; + } + return stateInfo; + }}, + {label:'Actions', key: function(row) { + var actions = ''; + if (row.state === 0) { + actions += '<a href="#" class="cancelTrigger btn btn-danger" data-uuid="' + row.uuid + '" data-query="' + row.query + '"><i class="glyphicon glyphicon-ban-circle"></i> Cancel</a> '; + } + return actions; + }} + ], + }, + stateMap = { + $container : null, + currentTable : null, + currentFilter : null, + currentSort : null }, - stateMap = { $container : null }, jqueryMap = {}, - setJqueryMap, initModule, unloadModule, updateQueryList, waitForData, registerPageEvents, unregisterPageEvents; + setJqueryMap, initModule, unloadModule, drawTableList, drawQueries, registerPageEvents, unregisterPageEvents; setJqueryMap = function() { var $container = stateMap.$container; jqueryMap = { $container : $container, - $queryInfoHolder : $('#queryInfoHolder') + $tableHolder : $('#tableHolder'), + $queryHolder : $('#queryHolder'), + $filterHolder : $('#filterOptions'), + $filterText : $('#filterOptions .filterText') }; }; + registerPageEvents = function() { + jqueryMap.$tableHolder.on('click', '.list-group-item', function(){ + stateMap.currentTable = $(this).attr('href'); + + $('.list-group-item', jqueryMap.$tableHolder).removeClass('active'); + $('.list-group-item[href="' + stateMap.currentTable + '"]', jqueryMap.$tableHolder).addClass('active'); + drawQueries(); + return false; + }); + jqueryMap.$queryHolder.on('click', 'a.cancelTrigger', function(){ + var uuid = $(this).data('uuid'), query = $(this).data('query'); + var modalContent = blurconsole.browserUtils.modal('confirmDelete', 'Confirm Query Cancel', 'You are about to cancel the query [' + query + ']. Are you sure you want to do this?', [ + {classes: 'btn-primary killQuery', label: 'Stop Query'}, + {classes: 'btn-default cancel', label: 'Cancel', data: {dismiss:'modal'}} + ], 'medium'); + + var modal = $(modalContent).modal().on('shown.bs.modal', function(e){ + $(e.currentTarget).on('click', '.killQuery', function() { + blurconsole.model.queries.cancelQuery(uuid); + modal.modal('hide'); + }); + }).on('hidden.bs.modal', function(e) { + $(e.currentTarget).remove(); + }); + return false; + }); + + jqueryMap.$filterHolder.on('click', '.filterTrigger', function() { + var filterVal = jqueryMap.$filterText.val(); + + stateMap.currentFilter = filterVal; + drawQueries(); + }); + }; + + unregisterPageEvents = function() { + if (jqueryMap.$tableHolder) { + jqueryMap.$tableHolder.off(); + } + }; + + drawTableList = function() { + var clusters = blurconsole.model.tables.getClusters(); + + if (clusters) { + jqueryMap.$tableHolder.html(''); + clusters.sort(); + $.each(clusters, function(i, cluster){ + var panelContent, tables = blurconsole.model.tables.getEnabledTables(cluster); + + panelContent = + '<div class="panel panel-default">' + + '<div class="panel-heading">' + + '<h3 class="panel-title">' + cluster + '</h3>' + + '</div>' + + '<div class="panel-body">'; + if (tables.length > 0) { + tables.sort(function(a, b){ return a.name > b.name; }); + panelContent += '<div class="list-group">'; + + $.each(tables, function(i, table){ + panelContent += '<a href="' + table.name + '" class="list-group-item'; + if (table.name === stateMap.currentTable) { + panelContent += ' active'; + drawQueries(); + } + panelContent += '">' + table.name + '</a>'; + }); + + panelContent += '</div>'; + } else { + panelContent += '<div class="alert alert-warning">There are not any enabled tables!</div>'; + } + panelContent += '</div></div>'; + jqueryMap.$tableHolder.append(panelContent); + }); + } else { + jqueryMap.$tableHolder.html('<div class="alert alert-warning">There are no clusters of tables!</div>'); + } + }; + + drawQueries = function() { + if (stateMap.currentTable){ + jqueryMap.$queryHolder.html(blurconsole.browserUtils.table(configMap.queryDef, blurconsole.model.queries.queriesForTable(stateMap.currentTable, stateMap.currentSort, stateMap.currentFilter))); + } else { + jqueryMap.$queryHolder.html('<div class="alert alert-info">Select a table on the left to see the current queries</div>'); + } + }; + initModule = function($container) { $container.load(configMap.view, function() { stateMap.$container = $container; setJqueryMap(); - $.gevent.subscribe(jqueryMap.$container, 'queries-updated', updateQueryList); - //waitForData(); - //registerPageEvents(); + $.gevent.subscribe(jqueryMap.$container, 'queries-updated', drawQueries); + $.gevent.subscribe(jqueryMap.$container, 'tables-updated', drawTableList); + registerPageEvents(); }); return true; }; unloadModule = function() { $.gevent.unsubscribe(jqueryMap.$container, 'queries-updated'); - //unregisterPageEvents(); + $.gevent.unsubscribe(jqueryMap.$container, 'tables-updated'); + unregisterPageEvents(); }; return { http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/5ccdd5e9/contrib/blur-console/ui/app/scripts/blurconsole.tables.js ---------------------------------------------------------------------- diff --git a/contrib/blur-console/ui/app/scripts/blurconsole.tables.js b/contrib/blur-console/ui/app/scripts/blurconsole.tables.js index 2ea8323..cb2a6f4 100644 --- a/contrib/blur-console/ui/app/scripts/blurconsole.tables.js +++ b/contrib/blur-console/ui/app/scripts/blurconsole.tables.js @@ -24,7 +24,9 @@ blurconsole.tables = (function () { var configMap = { view : 'views/tables.tpl.html', enabledDef : [ - {label:'Table Name', key:'name'}, + {label:'Table Name', key: function(row){ + return row.name + ' <i class="glyphicon glyphicon-exclamation-sign" data-table="' + row.name + '" style="display:none" title="Activity detected"></i>'; + }}, {label:'Row Count', key: 'rowCount'}, {label:'Record Count', key: 'recordCount'}, {label:'Actions', key: function(row) { @@ -46,7 +48,7 @@ blurconsole.tables = (function () { }, stateMap = { $container : null }, jqueryMap = {}, - setJqueryMap, initModule, unloadModule, updateTableList, buildTabs, waitForData, registerPageEvents, unregisterPageEvents; + setJqueryMap, initModule, unloadModule, updateTableList, buildTabs, waitForData, registerPageEvents, unregisterPageEvents, updateActivityIndicators; setJqueryMap = function() { var $container = stateMap.$container; @@ -59,6 +61,7 @@ blurconsole.tables = (function () { unloadModule = function() { $.gevent.unsubscribe(jqueryMap.$container, 'tables-updated'); + $.gevent.unsubscribe(jqueryMap.$container, 'queries-updated'); unregisterPageEvents(); }; @@ -67,6 +70,7 @@ blurconsole.tables = (function () { stateMap.$container = $container; setJqueryMap(); $.gevent.subscribe(jqueryMap.$container, 'tables-updated', updateTableList); + $.gevent.subscribe(jqueryMap.$container, 'queries-updated', updateActivityIndicators); waitForData(); registerPageEvents(); }); @@ -90,7 +94,7 @@ blurconsole.tables = (function () { if (needsTabs) { tabMarkup = '<ul class="nav nav-tabs">'; tabMarkup += $.map(clusters, function(cluster, idx) { - return '<li class="' + (idx === 0 ? 'active' : '') + '"><a href="#' + cluster + '_pane" data-toggle="tab">' + cluster + '</a></li>'; + return '<li class="' + (idx === 0 ? 'active' : '') + '"><a href="#' + cluster + '_pane" data-toggle="tab">' + cluster + ' <i class="glyphicon glyphicon-exclamation-sign" style="display:none" title="Activity detected"></i></a></li>'; }).join(''); tabMarkup += '</ul>'; @@ -161,7 +165,6 @@ blurconsole.tables = (function () { // Delete Table jqueryMap.$tableInfoHolder.on('click', 'a.deleteTrigger', function() { var tableName = $(this).data('name'); - console.log('delete:' + tableName); var modalContent = blurconsole.browserUtils.modal('confirmDelete', 'Confirm Table Deletion', 'You are about to delete table ' + tableName + '. Are you sure you want to do this? If so, do you also want to delete the underlying table data?', [ {classes: 'btn-warning tableOnly', label: 'Table Only'}, {classes: 'btn-danger tableAndData', label: 'Table And Data'}, @@ -189,6 +192,30 @@ blurconsole.tables = (function () { } }; + updateActivityIndicators = function() { + var clusters = blurconsole.model.tables.getClusters(); + + $.each(clusters, function(i, cluster) { + var clusterHasActivity = false, + tables = blurconsole.model.tables.getEnabledTables(cluster); + + $.each(tables, function(i, table){ + if (blurconsole.model.queries.tableHasActivity(table.name)) { + clusterHasActivity = true; + $('i[data-table="' + table.name + '"]').show(); + } else { + $('i[data-table="' + table.name + '"]').hide(); + } + }); + + if (clusterHasActivity) { + $('a[href="#' + cluster +'_pane"] i').show(); + } else { + $('a[href="#' + cluster +'_pane"] i').hide(); + } + }); + }; + return { initModule : initModule, unloadModule : unloadModule http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/5ccdd5e9/contrib/blur-console/ui/app/styles/blurconsole.queries.scss ---------------------------------------------------------------------- diff --git a/contrib/blur-console/ui/app/styles/blurconsole.queries.scss b/contrib/blur-console/ui/app/styles/blurconsole.queries.scss new file mode 100644 index 0000000..e473517 --- /dev/null +++ b/contrib/blur-console/ui/app/styles/blurconsole.queries.scss @@ -0,0 +1,22 @@ +/* +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. +*/ + +#filterOptions { + margin-bottom: 5px; +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/5ccdd5e9/contrib/blur-console/ui/app/views/queries.tpl.html ---------------------------------------------------------------------- diff --git a/contrib/blur-console/ui/app/views/queries.tpl.html b/contrib/blur-console/ui/app/views/queries.tpl.html index 10b525c..1667e64 100644 --- a/contrib/blur-console/ui/app/views/queries.tpl.html +++ b/contrib/blur-console/ui/app/views/queries.tpl.html @@ -17,4 +17,24 @@ KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> -<div id="queryInfoHolder"><img src="images/ajax-loader.gif"></div> \ No newline at end of file +<div class="row"> + <div id="tableHolder" class="col-md-4"> + + </div> + <div class="col-md-8"> + <div class="row"> + <div id="filterOptions" class="col-md-12"> + <div class="input-group col-md-4 pull-right"> + <input class="form-control filterText" placeholder="Filter" type="text"> + <span class="input-group-btn"> + <button class="btn btn-default filterTrigger" type="button">Go!</button> + </span> + </div> + </div> + <div id="queryHolder" class="col-md-12"> + + </div> + </div> + + </div> +</div> \ No newline at end of file
