-
Notifications
You must be signed in to change notification settings - Fork 37
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Include a view showing the status of the cluster
When a node is part of a cluster, i.e. /info/options returns a ClusterSize > 1, a new menu item will appear in the UI that allows the user to get a glance of the cluster the node forms a part of
- Loading branch information
1 parent
f177ebc
commit 3383d8c
Showing
23 changed files
with
385 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
define([ | ||
'angular', | ||
'uiRouter', | ||
'./controllers/_index', | ||
'./services/_index', | ||
'./templates/templates' | ||
], function (ng) { | ||
|
||
'use strict'; | ||
return ng.module('es-ui.clusterstatus', [ | ||
'ui.router', | ||
'es-ui.clusterstatus.templates', | ||
'es-ui.clusterstatus.services', | ||
'es-ui.clusterstatus.controllers', | ||
]); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
angular.module('esManager') | ||
.factory('urls', function urls(){ | ||
return{ | ||
gossip:'/gossip', | ||
options:'/info/options', | ||
system:{ | ||
info: '/info' | ||
} | ||
} | ||
}); |
40 changes: 40 additions & 0 deletions
40
src/js/modules/clusterstatus/controllers/ClusterStatusListCtrl.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
define(['./_module'], function (app) { | ||
|
||
'use strict'; | ||
|
||
return app.controller('ClusterStatusListCtrl', ['$scope', 'poller', 'ClusterStatusService', 'InfoService', | ||
function ClusterStatusListCtrl($scope, poller, clusterStatusService, infoService) { | ||
infoService.getOptions().then( | ||
function(response){ | ||
var options = response.data; | ||
for (var index in options) { | ||
if(options[index].name == "ClusterSize" && options[index].value > 1){ | ||
setupGossipPoller(); | ||
} | ||
} | ||
}, | ||
function(){ | ||
|
||
}); | ||
function setupGossipPoller(){ | ||
var gossipQuery = poller.create({ | ||
interval: 1000, | ||
action: clusterStatusService.gossip, | ||
params: [] | ||
}); | ||
gossipQuery.start(); | ||
gossipQuery.promise.then(null, null, function (response) { | ||
$scope.lastUpdatedTime = new Date(); | ||
if (response.error) { | ||
$scope.errorMessage = "couldn't connect to manager"; | ||
} else { | ||
$scope.errorMessage = ''; | ||
$scope.nodes = response.members; | ||
} | ||
}); | ||
} | ||
$scope.$on('$destroy', function () { | ||
poller.clear(); | ||
}); | ||
}]); | ||
}); |
33 changes: 33 additions & 0 deletions
33
src/js/modules/clusterstatus/controllers/ClusterStatusSnapshotCtrl.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
define(['./_module'], function (app) { | ||
|
||
'use strict'; | ||
|
||
return app.controller('ClusterStatusSnapshotCtrl', ['$scope', 'dateFilter', 'poller', 'SprintfService', 'ClusterStatusService', | ||
function ClusterStatusSnapshotCtrl($scope, dateFilter, poller, sprintf, clusterStatusService) { | ||
function format(data) { | ||
var nodes = data.members; | ||
var snapshotLines = sprintf.format('%s\n', 'Snapshot taken at ' + dateFilter(new Date(), 'yyyy-MM-d HH:mm:ss')); | ||
snapshotLines += sprintf.format("%-31s %-31s %-23s %-23s %-7s %-14s %-19s %-10s\n", "Internal Tcp", "External Tcp", "Internal Http", "External Http", "Status", "State", "Timestamp (UTC)", "Checkpoints"); | ||
for (var i = 0; i < nodes.length; i++) { | ||
var node = nodes[i]; | ||
snapshotLines += sprintf.format("%-30s %-30s %-22s %-22s %-6s %-12s %19s %-90s\n", | ||
node.internalTcpIp + ':' + node.internalTcpPort + ' (' + (node.internalSecureTcpPort || 'n/a') + ')', | ||
node.externalTcpIp + ':' + node.externalTcpPort + ' (' + (node.externalSecureTcpPort || 'n/a') + ')', | ||
node.internalHttpIp + ':' + node.internalHttpPort, | ||
node.externalHttpIp + ':' + node.externalHttpPort, | ||
node.isAlive ? 'Alive' : 'Dead', | ||
node.state, | ||
dateFilter(node.timeStamp, 'yyyy-MM-d HH:mm:ss'), | ||
node.state == 'Manager' | ||
? 'n/a' | ||
: sprintf.format('L%d/W%d/C%d/E%d@%d:{%s}', node.lastCommitPosition, node.writerCheckpoint, node.chaserCheckpoint, | ||
node.epochNumber, node.epochPosition, node.epochId)) | ||
}; | ||
$scope.snapshot = snapshotLines; | ||
} | ||
$scope.$on('$destroy', function () { | ||
poller.clear(); | ||
}); | ||
clusterStatusService.gossip().success(format); | ||
}]); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
define([ | ||
'./ClusterStatusListCtrl', | ||
'./ClusterStatusSnapshotCtrl', | ||
], function () {}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
define(['angular'], function (ng) { | ||
'use strict'; | ||
return ng.module('es-ui.clusterstatus.controllers', [ | ||
]); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
/* global define */ | ||
/*jshint sub: true */ | ||
|
||
define(['./_index'], function (app) { | ||
'use strict'; | ||
|
||
return app.config([ | ||
'$stateProvider', | ||
function ($stateProvider) { | ||
|
||
$stateProvider | ||
// ========================================CLUSTERSTATUS============ | ||
.state('clusterstatus', { | ||
parent: 'app', | ||
url: 'clusterstatus', | ||
templateUrl: 'clusterstatus.tpl.html', | ||
abstract: true, | ||
data: { | ||
title: 'Cluster Status' | ||
} | ||
}) | ||
.state('clusterstatus.list', { | ||
url: '', | ||
templateUrl: 'clusterstatus.list.tpl.html', | ||
controller: 'ClusterStatusListCtrl', | ||
|
||
data: { | ||
title: 'Cluster Status' | ||
} | ||
}) | ||
.state('clusterstatus.snapshot', { | ||
url: '/snapshot', | ||
templateUrl: 'clusterstatus.snapshot.tpl.html', | ||
controller: 'ClusterStatusSnapshotCtrl', | ||
data: { | ||
title: 'Cluster Status Snapshot' | ||
} | ||
}); | ||
}]); | ||
}); |
21 changes: 21 additions & 0 deletions
21
src/js/modules/clusterstatus/services/ClusterStatusService.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
define(['./_module'], function (app) { | ||
|
||
'use strict'; | ||
|
||
return app.provider('ClusterStatusService', function () { | ||
|
||
this.$get = [ | ||
'$http', 'urls', 'UrlBuilder', | ||
function ($http, urls, urlBuilder) { | ||
|
||
return { | ||
gossip: function () { | ||
var url = urlBuilder.build(urls.gossip); | ||
|
||
return $http.get(url); | ||
} | ||
}; | ||
} | ||
]; | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
define([ | ||
'./ClusterStatusService', | ||
], function () {}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
define(['angular'], function (ng) { | ||
'use strict'; | ||
return ng.module('es-ui.clusterstatus.services', []); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
define(['angular'], function (angular) {'use strict'; (function(module) { | ||
try { | ||
module = angular.module('es-ui.clusterstatus.templates'); | ||
} catch (e) { | ||
module = angular.module('es-ui.clusterstatus.templates', []); | ||
} | ||
module.run(['$templateCache', function($templateCache) { | ||
$templateCache.put('clusterstatus.list.tpl.html', | ||
'<header class=page-header><h2 class=page-title>Cluster Status</h2><ul class=page-nav><li class=page-nav__item><a ui-sref=^.snapshot>Snapshot</a></li></ul></header><div><table class=table-nodes><thead><tr><th>Internal Tcp</th><th>External Tcp</th><th>Internal Http</th><th>External Http</th><th>Status</th><th>State</th><th>Timestamp (UTC)</th><th>Checkpoints</th><th>Actions</th></tr><tr><th></th><th></th><th></th><th></th><th></th><th></th><th></th><th></th><th></th></tr></thead><tbody><tr ng-repeat="node in nodes" ng-class="{dead: !node.isAlive}"><td>{{ node.internalTcpIp }}:{{ node.internalTcpPort }}</td><td>{{ node.externalTcpIp }}:{{ node.externalTcpPort }}</td><td>{{ node.internalHttpIp }}:{{ node.internalHttpPort }}</td><td>{{ node.externalHttpIp }}:{{ node.externalHttpPort }}</td><td ng-class="{dead: !node.isAlive}"><text ng-if=node.isAlive>Alive</text><text ng-if=!node.isAlive>Dead</text></td><td><text ng-if="node.state == \'Master\'"><b>{{ node.state }}</b></text><text ng-if="node.state == \'Manager\'" style=color:lightgray>{{ node.state }}</text><text ng-if="node.state != \'Master\' && node.state != \'Manager\'">{{ node.state }}</text></td><td>{{ node.timeStamp | date : \'yyyy-MM-d HH:mm:ss\' }}</td><td><text ng-if="node.state == \'Manager\'">n/a</text><text ng-if="node.state != \'Manager\'">L{{ node.lastCommitPosition}} / W {{node.writerCheckpoint}} / C {{node.chaserCheckpoint}}<br>E{{ node.epochNumber }} @ {{ node.epochPosition }} : { {{ node.epochId }} }</text></td><td style=text-align:center><ul class=page-nav><li class=page-nav__item><a ng-href=http://{{node.externalHttpIp}}:{{node.externalHttpPort}}/ping target=_blank>ping</a></li><li class=page-nav__item><a ng-href=http://{{node.externalHttpIp}}:{{node.externalHttpPort}} target=_blank>show website</a></li><li class=page-nav__item><a ng-href=http://{{node.internalHttpIp}}:{{node.internalHttpPort}}/gossip target=_blank>show gossip</a></li></ul></td></tr><tr ng-hide=nodes><td colspan=9><em>No nodes in the cluster</em></td></tr></tbody></table><div class=last-updated>Last updated: <span>{{ lastUpdatedTime | date : \'yyyy-MM-d HH:mm:ss\' }}</span></div></div><script>function selectText(element) {\n' + | ||
' var doc = document\n' + | ||
' , text = doc.getElementById(element)\n' + | ||
' , range\n' + | ||
' , selection;\n' + | ||
' if (doc.body.createTextRange) { //ms\n' + | ||
' range = doc.body.createTextRange();\n' + | ||
' range.moveToElementText(text);\n' + | ||
' range.select();\n' + | ||
' } else if (window.getSelection) { //all others\n' + | ||
' selection = window.getSelection();\n' + | ||
' range = doc.createRange();\n' + | ||
' range.selectNodeContents(text);\n' + | ||
' selection.removeAllRanges();\n' + | ||
' selection.addRange(range);\n' + | ||
' }\n' + | ||
' }</script>'); | ||
}]); | ||
})(); | ||
|
||
(function(module) { | ||
try { | ||
module = angular.module('es-ui.clusterstatus.templates'); | ||
} catch (e) { | ||
module = angular.module('es-ui.clusterstatus.templates', []); | ||
} | ||
module.run(['$templateCache', function($templateCache) { | ||
$templateCache.put('clusterstatus.snapshot.tpl.html', | ||
'<header class=page-header><h2 class=page-title>Cluster Status Snapshot</h2><ul class=page-nav><li class=page-nav__item><a ui-sref=clusterstatus.list>Back</a></li></ul></header><pre ng-bind=snapshot>\n' + | ||
'\n' + | ||
'</pre>'); | ||
}]); | ||
})(); | ||
|
||
(function(module) { | ||
try { | ||
module = angular.module('es-ui.clusterstatus.templates'); | ||
} catch (e) { | ||
module = angular.module('es-ui.clusterstatus.templates', []); | ||
} | ||
module.run(['$templateCache', function($templateCache) { | ||
$templateCache.put('clusterstatus.tpl.html', | ||
'<div ui-view></div>'); | ||
}]); | ||
})(); | ||
}); |
99 changes: 99 additions & 0 deletions
99
src/js/modules/clusterstatus/views/clusterstatus.list.tpl.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
<header class="page-header"> | ||
<h2 class="page-title">Cluster Status</h2> | ||
<ul class="page-nav"> | ||
<li class="page-nav__item"> | ||
<a ui-sref="^.snapshot">Snapshot</a> | ||
</li> | ||
</ul> | ||
</header> | ||
<div> | ||
<table class="table-nodes"> | ||
<thead> | ||
<tr> | ||
<th>Internal Tcp</th> | ||
<th>External Tcp</th> | ||
<th>Internal Http</th> | ||
<th>External Http</th> | ||
<th>Status</th> | ||
<th>State</th> | ||
<th>Timestamp (UTC)</th> | ||
<th>Checkpoints</th> | ||
<th>Actions</th> | ||
</tr> | ||
<tr> | ||
<th></th> | ||
<th></th> | ||
<th></th> | ||
<th></th> | ||
<th></th> | ||
<th></th> | ||
<th></th> | ||
<th></th> | ||
<th></th> | ||
</tr> | ||
</thead> | ||
<tbody> | ||
<tr ng-repeat="node in nodes" ng-class="{dead: !node.isAlive}"> | ||
<td>{{ node.internalTcpIp }}:{{ node.internalTcpPort }}</td> | ||
<td>{{ node.externalTcpIp }}:{{ node.externalTcpPort }}</td> | ||
<td>{{ node.internalHttpIp }}:{{ node.internalHttpPort }}</td> | ||
<td>{{ node.externalHttpIp }}:{{ node.externalHttpPort }}</td> | ||
<td ng-class="{dead: !node.isAlive}"> | ||
<text ng-if="node.isAlive">Alive</text> | ||
<text ng-if="!node.isAlive">Dead</text> | ||
</td> | ||
<td> | ||
<text ng-if="node.state == 'Master'"><b>{{ node.state }}</b></text> | ||
<text ng-if="node.state == 'Manager'" style="color:lightgray">{{ node.state }}</text> | ||
<text ng-if="node.state != 'Master' && node.state != 'Manager'">{{ node.state }}</text> | ||
</td> | ||
<td>{{ node.timeStamp | date : 'yyyy-MM-d HH:mm:ss' }}</td> | ||
<td> | ||
<text ng-if="node.state == 'Manager'">n/a</text> | ||
<text ng-if="node.state != 'Manager'"> | ||
L{{ node.lastCommitPosition}} / W {{node.writerCheckpoint}} / C {{node.chaserCheckpoint}}<br /> | ||
E{{ node.epochNumber }} @ {{ node.epochPosition }} : { {{ node.epochId }} } | ||
</text> | ||
</td> | ||
<td style="text-align:center;"> | ||
<ul class="page-nav"> | ||
<li class="page-nav__item"> | ||
<a ng-href="http://{{node.externalHttpIp}}:{{node.externalHttpPort}}/ping" target="_blank">ping</a> | ||
</li> | ||
<li class="page-nav__item"> | ||
<a ng-href="http://{{node.externalHttpIp}}:{{node.externalHttpPort}}" target="_blank">show website</a> | ||
</li> | ||
<li class="page-nav__item"> | ||
<a ng-href="http://{{node.internalHttpIp}}:{{node.internalHttpPort}}/gossip" target="_blank">show gossip</a> | ||
</li> | ||
</ul> | ||
</td> | ||
</tr> | ||
<tr ng-hide="nodes"> | ||
<td colspan="9"> | ||
<em>No nodes in the cluster</em> | ||
</td> | ||
</tr> | ||
</tbody> | ||
</table> | ||
<div class="last-updated">Last updated: <span>{{ lastUpdatedTime | date : 'yyyy-MM-d HH:mm:ss' }}</span></div> | ||
</div> | ||
<script type="text/javascript"> | ||
function selectText(element) { | ||
var doc = document | ||
, text = doc.getElementById(element) | ||
, range | ||
, selection; | ||
if (doc.body.createTextRange) { //ms | ||
range = doc.body.createTextRange(); | ||
range.moveToElementText(text); | ||
range.select(); | ||
} else if (window.getSelection) { //all others | ||
selection = window.getSelection(); | ||
range = doc.createRange(); | ||
range.selectNodeContents(text); | ||
selection.removeAllRanges(); | ||
selection.addRange(range); | ||
} | ||
} | ||
</script> |
Oops, something went wrong.