Skip to content

Commit cb2e5e3

Browse files
committed
Failed messages screen notifies user of new messages, fixes #48
Added option to remove heartbeats associated with endpoint.
1 parent 61b40d3 commit cb2e5e3

File tree

10 files changed

+82
-56
lines changed

10 files changed

+82
-56
lines changed

src/ServicePulse.Host/ServicePulse.Host.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@
106106
<Content Include="app\img\icons-small.png" />
107107
<Content Include="app\img\ie7-forbidden-logo.jpg" />
108108
<Content Include="app\img\i_16_radio.png" />
109+
<Content Include="app\img\loader_spinner.gif" />
109110
<Content Include="app\img\logo.png" />
110111
<Content Include="app\img\logo20.png" />
111112
<Content Include="app\img\progress.gif" />

src/ServicePulse.Host/app/css/app.css

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,4 +70,22 @@
7070
width: 96.489362%;
7171
*width: 96.489362%;
7272
}
73+
}
74+
75+
.newMessages {
76+
padding-top: 15px;
77+
background-color: #f7f7f9;
78+
border: 1px solid #e1e1e8;
79+
cursor: pointer;
80+
}
81+
82+
.newMessages:hover {
83+
background-color: #DBDBDB;
84+
}
85+
86+
.loading {
87+
background-image: url('/img/loader_spinner.gif');
88+
background-position: center;
89+
background-repeat: no-repeat;
90+
height: 65px;
7391
}
7.6 KB
Loading

src/ServicePulse.Host/app/js/alerts/alerts.tpl.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,6 @@ <h2><i class="fa-icon-info-sign"></i><span class="break"></span>Latest events</h
1515
</div>
1616
</div>
1717
<div class="alert alert-success" ng-show='!loadingData && model.length == 0'>No events!</div>
18-
<div class="alert alert-info" ng-show='loadingData'><strong>Loading data ...</strong></div>
18+
<div class="loading" ng-show='loadingData'></div>
1919
</div>
2020
</div>

src/ServicePulse.Host/app/js/custom_checks/customChecks.tpl.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ <h2><i class="fa-icon-check"></i><span class="break"></span>Showing {{model.tota
2727
</div>
2828
</div>
2929
<div class="alert alert-success" ng-show='!loadingData && model.total == 0'>No failed custom checks</div>
30-
<div class="alert alert-info" ng-show='loadingData'><strong>Loading data ...</strong></div>
30+
<div class="loading" ng-show='loadingData'></div>
3131
</div>
3232
</div>
3333
</div>

src/ServicePulse.Host/app/js/endpoints/endpoints.js

Lines changed: 16 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -4,50 +4,29 @@ angular.module('endpoints', [])
44
.config(['$routeProvider', function($routeProvider) {
55
$routeProvider.when('/endpoints', { templateUrl: 'js/endpoints/endpoints.tpl.html', controller: 'EndpointsCtrl' });
66
}])
7-
.controller('EndpointsCtrl', ['$scope', 'serviceControlService', 'streamService', function ($scope, serviceControlService, streamService) {
7+
.controller('EndpointsCtrl', ['$scope', 'serviceControlService', '$timeout', function ($scope, serviceControlService, $timeout) {
88

99
$scope.model = [];
1010

11-
serviceControlService.getHeartbeatsList().then(function (heartbeats) {
12-
$scope.model = heartbeats;
13-
});
14-
15-
streamService.subscribe($scope, 'EndpointFailedToHeartbeat', function (message) {
16-
processMessage(message, false, message.last_received_at);
17-
});
18-
19-
streamService.subscribe($scope, 'EndpointHeartbeatRestored', function (message) {
20-
processMessage(message, true, message.restored_at);
21-
});
22-
23-
streamService.subscribe($scope, 'HeartbeatingEndpointDetected', function (message) {
24-
processMessage(message, true, message.detected_at);
25-
});
11+
var timeoutId;
2612

13+
$scope.removeEndpoint = function(id) {
14+
serviceControlService.deleteEndpoint(id);
15+
};
16+
2717
$scope.$on('$destroy', function () {
28-
streamService.unsubscribe($scope, 'EndpointFailedToHeartbeat');
29-
streamService.unsubscribe($scope, 'HeartbeatingEndpointDetected');
30-
streamService.unsubscribe($scope, 'EndpointHeartbeatRestored');
18+
$timeout.cancel(timeoutId);
3119
});
3220

33-
function processMessage(message, active, lastUpdatedAt) {
34-
var idx = findHeartbeat(message.endpoint, message.machine);
35-
36-
if (idx == -1) {
37-
$scope.model.push(angular.extend({ active: active, last_sent_at: lastUpdatedAt }, message));
38-
} else {
39-
$scope.model[idx].active = active;
40-
$scope.model[idx].last_sent_at = lastUpdatedAt;
41-
}
21+
function updateUI() {
22+
serviceControlService.getHeartbeatsList().then(function(heartbeats) {
23+
$scope.model = heartbeats;
24+
});
4225
}
4326

44-
function findHeartbeat(endpoint, machine) {
45-
for (var i = 0; i < $scope.model.length; i++) {
46-
if ($scope.model[i].endpoint === endpoint && $scope.model[i].machine === machine) {
47-
return i;
48-
}
49-
}
50-
51-
return -1;
52-
};
27+
timeoutId = $timeout(function () {
28+
updateUI();
29+
}, 5000);
30+
31+
updateUI();
5332
}]);

src/ServicePulse.Host/app/js/endpoints/endpoints.tpl.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
<div style="margin: 5px;" ng-class="{'alert-success': endpoint.reported_status != 'dead', 'alert-danger': endpoint.reported_status == 'dead'}">
1515
<h4>{{endpoint.originating_endpoint.name}}@{{endpoint.originating_endpoint.machine}}</h4>
1616
<p>Latest heartbeat received: <sp-moment date="{{endpoint.last_report_at}}" /></p>
17+
<button class="btn btn-danger" ng-click="removeEndpoint(endpoint.id)">Remove</button>
1718
</div>
1819
</div>
1920
</div>

src/ServicePulse.Host/app/js/failed_messages/failedMessages.js

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,36 @@ angular.module('failedMessages', [])
66
}])
77
.controller('FailedMessagesCtrl', ['$scope', 'serviceControlService', 'streamService', '$routeParams', function ($scope, serviceControlService, streamService, $routeParams) {
88

9-
$scope.model = { total: 0, failedMessages: [], failedMessagesStats: [], selectedIds:[] };
9+
$scope.model = { total: 0, failedMessages: [], failedMessagesStats: [], selectedIds:[], newMessages: 0 };
1010
$scope.loadingData = false;
1111
$scope.disableLoadingData = false;
1212

1313
var page = 1;
14+
15+
function init() {
16+
page = 1;
17+
$scope.model.failedMessages = [];
18+
$scope.model.selectedIds = [];
19+
$scope.disableLoadingData = false;
20+
}
1421

15-
function load(sortKey, page) {
16-
serviceControlService.getFailedMessages(sortKey, page).then(function (response) {
22+
function load() {
23+
if ($scope.loadingData) {
24+
return;
25+
}
1726

18-
$scope.loadingData = false;
19-
27+
$scope.loadingData = true;
28+
29+
serviceControlService.getFailedMessages($routeParams.sort, page).then(function (response) {
2030
$scope.model.failedMessages = $scope.model.failedMessages.concat(response.data);
2131
$scope.model.total = response.total;
22-
32+
2333
if ($scope.model.failedMessages.length >= $scope.model.total) {
2434
$scope.disableLoadingData = true;
2535
}
36+
37+
$scope.loadingData = false;
38+
page++;
2639
});
2740

2841
serviceControlService.getFailedMessageStats().then(function (failedMessagesStats) {
@@ -31,12 +44,8 @@ angular.module('failedMessages', [])
3144
};
3245

3346
$scope.loadMoreResults = function () {
34-
if ($scope.loadingData) {
35-
return;
36-
}
3747

38-
$scope.loadingData = true;
39-
load($routeParams.sort, page++);
48+
load();
4049
};
4150

4251
$scope.toggleRowSelect = function (row) {
@@ -54,6 +63,12 @@ angular.module('failedMessages', [])
5463
}
5564
};
5665

66+
$scope.refreshResults = function () {
67+
init();
68+
load();
69+
$scope.model.newMessages = 0;
70+
};
71+
5772
$scope.retryAll = function() {
5873
serviceControlService.retryAllFailedMessages();
5974
};
@@ -71,8 +86,8 @@ angular.module('failedMessages', [])
7186
}
7287
};
7388

74-
streamService.subscribe($scope, 'MessageFailed', function() {
75-
$scope.model.total++;
89+
streamService.subscribe($scope, 'MessageFailed', function () {
90+
$scope.model.newMessages++;
7691
});
7792

7893
$scope.$on('$destroy', function () {

src/ServicePulse.Host/app/js/failed_messages/failedMessages.tpl.html

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,12 @@ <h3>Message Types</h3>
4747
<div class="row-fluid">
4848
<div class="box span12">
4949
<div class="box-header" data-original-title>
50-
<h2><i class="fa-icon-envelope"></i><span class="break"></span>Showing {{model.failedMessages.length}} message(s)</h2>
50+
<h2><i class="fa-icon-envelope"></i><span class="break"></span>Showing {{model.failedMessages.length}} message(s) <i ng-show="!disableLoadingData">(scroll down to load more)</i></h2>
5151
</div>
5252
<div class="box-content">
5353
<div class="btn-toolbar">
5454
<button class="btn" ng-click="retrySelected()" ng-disabled="model.selectedIds.length == 0"><i class="icon-repeat"></i> Retry {{model.selectedIds.length}} selected</button>
55-
<button class="btn" ng-click="retryAll()" ng-disabled="model.total == 0"><i class="icon-asterisk"></i> Retry all messages)</button>
55+
<button class="btn" ng-click="retryAll()" ng-disabled="model.total == 0"><i class="icon-asterisk"></i> Retry all messages</button>
5656
<div class="btn-group pull-right">
5757
<a class="btn btn-link dropdown-toggle"
5858
data-toggle="dropdown"
@@ -66,6 +66,8 @@ <h2><i class="fa-icon-envelope"></i><span class="break"></span>Showing {{model.f
6666
</ul>
6767
</div>
6868
</div>
69+
<div class="newMessages" ng-show="model.newMessages > 1" ng-click="refreshResults()"><p class="text-center">{{model.newMessages}} new messages</p></div>
70+
<div class="newMessages" ng-show="model.newMessages == 1" ng-click="refreshResults()"><p class="text-center">{{model.newMessages}} new message</p></div>
6971
<div infinite-scroll="loadMoreResults()" infinite-scroll-distance="0" infinite-scroll-disabled="disableLoadingData">
7072
<div class="scRow" ng-repeat="row in model.failedMessages">
7173
<div class="row-fluid scSelectableRow" ng-class="{rowSelected: row.selected == true}" ng-click="toggleRowSelect(row)" style="cursor: pointer;">
@@ -78,14 +80,14 @@ <h2><i class="fa-icon-envelope"></i><span class="break"></span>Showing {{model.f
7880
<div class="span2 text-right"><sp-moment date="{{row.time_sent}}" /></div>
7981
</div>
8082
<div class="row-fluid">
81-
<div class="span8"><code>{{row.failure_details.exception.message}}</code></div>
83+
<div class="span8"><pre>{{row.failure_details.exception.message}}</pre></div>
8284
<div class="span4 text-right" title="In: {{row.receiving_endpoint.name}} on {{row.receiving_endpoint.machine}}">in {{row.receiving_endpoint.name}} on {{row.receiving_endpoint.machine}}</div>
8385
</div>
8486
</div>
8587
</div>
8688
</div>
8789
<div class="alert alert-success" ng-show='!loadingData && model.total == 0'>No failed messages</div>
88-
<div class="alert alert-info" ng-show='loadingData'><strong>Loading data ...</strong></div>
90+
<div class="loading" ng-show='loadingData'></div>
8991
</div>
9092
</div>
9193
</div>

src/ServicePulse.Host/app/js/services/serviceControlService.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,16 @@ angular.module('services.serviceControlService', [])
7777
});
7878
};
7979

80+
this.deleteEndpoint = function (id) {
81+
$http.delete(scConfig.service_control_url + '/heartbeats/' + id)
82+
.success(function () {
83+
notifications.pushForCurrentRoute('Endpoint deleted', 'info');
84+
})
85+
.error(function () {
86+
notifications.pushForCurrentRoute('Endpoint deletion failed', 'error');
87+
});
88+
};
89+
8090
this.getEndpoints = function() {
8191
return $http.get(scConfig.service_control_url + '/endpoints').then(function (response) {
8292
return response.data;

0 commit comments

Comments
 (0)