feat(webui): new Health screen

- add realtime chart
  - Total Status Code Count
  - Average response time
  - remove status code count
  - D3 & NVD3 & Angular NVD3
This commit is contained in:
Fernandez Ludovic 2015-10-07 22:31:00 +02:00
parent 398dfbd8a5
commit 28458345b4
10 changed files with 252 additions and 51 deletions

View file

@ -6,21 +6,199 @@
var vm = this; var vm = this;
vm.health = Health.get(); vm.graph = {
averageResponseTime: {},
totalStatusCodeCount: {}
}
vm.graph.totalStatusCodeCount.options = {
"chart": {
type: 'discreteBarChart',
height: 200,
margin: {
top: 20,
right: 20,
bottom: 40,
left: 55
},
x: function (d) {
return d.label;
},
y: function (d) {
return d.value;
},
showValues: true,
valueFormat: function (d) {
return d3.format('d')(d);
},
transitionDuration: 50,
yAxis: {
axisLabelDistance: 30
}
},
"title": {
"enable": true,
"text": "Total Status Code Count",
"css": {
"textAlign": "center"
}
}
};
vm.graph.totalStatusCodeCount.data = [
{
key: "Total Status Code Count",
values: [
{
"label": "200",
"value": 0
}
]
}
];
/**
* Update Total Status Code Count graph
*
* @param {Object} totalStatusCodeCount Object from API
*/
function updateTotalStatusCodeCount(totalStatusCodeCount) {
// extract values
vm.graph.totalStatusCodeCount.data[0].values = [];
for (var code in totalStatusCodeCount) {
if (totalStatusCodeCount.hasOwnProperty(code)) {
vm.graph.totalStatusCodeCount.data[0].values.push({
label: code,
value: totalStatusCodeCount[code]
})
}
}
// Update Total Status Code Count graph render
if (vm.graph.totalStatusCodeCount.api) {
vm.graph.totalStatusCodeCount.api.update();
} else {
console.error('fail');
}
}
vm.graph.averageResponseTime.options = {
chart: {
type: 'lineChart',
height: 200,
margin: {
top: 20,
right: 40,
bottom: 40,
left: 55
},
transitionDuration: 50,
x: function (d) {
return d.x;
},
y: function (d) {
return d.y;
},
useInteractiveGuideline: true,
xAxis: {
tickFormat: function (d) {
return d3.time.format('%X')(new Date(d));
}
},
yAxis: {
tickFormat: function (d) {
return d3.format(',.1f')(d);
}
}
},
"title": {
"enable": true,
"text": "Average response time",
"css": {
"textAlign": "center"
}
}
};
var initialPoint = {
x: Date.now() - 3000,
y: 0
};
vm.graph.averageResponseTime.data = [
{
values: [initialPoint],
key: 'Average response time (ms)',
type: 'line',
color: '#2ca02c'
}
];
/**
* Update average response time graph
*
* @param {Number} x Coordinate X
* @param {Number} y Coordinate Y
*/
function updateAverageResponseTimeGraph(x, y) {
// x multiply 1000 by because unix time is in seconds and JS Date are in milliseconds
var data = {
x: x * 1000,
y: y * 1000
};
vm.graph.averageResponseTime.data[0].values.push(data);
// limit graph entries
if (vm.graph.averageResponseTime.data[0].values.length > 100) {
vm.graph.averageResponseTime.data[0].values.shift();
}
// Update Average Response Time graph render
if (vm.graph.averageResponseTime.api) {
vm.graph.averageResponseTime.api.update();
}
}
/**
* Load all graph's datas
*
* @param {Object} health Health data from server
*/
function loadData(health) {
// Load datas and update Average Response Time graph render
updateAverageResponseTimeGraph(health.unixtime, health.average_response_time_sec);
// Load datas and update Total Status Code Count graph render
updateTotalStatusCodeCount(health.total_status_code_count);
// set data's view
vm.health = health;
}
/**
* Action when load datas failed
*
* @param {Object} error Error state object
*/
function erroData(error) {
vm.health = {};
$log.error(error);
}
// first load
Health.get(loadData, erroData);
// Auto refresh data
var intervalId = $interval(function () { var intervalId = $interval(function () {
Health.get(function (health) { Health.get(loadData, erroData);
vm.health = health;
}, function (error) {
vm.health = {};
$log.error(error);
});
}, 3000); }, 3000);
// Stop auto refresh when page change
$scope.$on('$destroy', function () { $scope.$on('$destroy', function () {
$interval.cancel(intervalId); $interval.cancel(intervalId);
}); });
}]); }]);
})(); })();

View file

@ -2,45 +2,42 @@
<h1 class="text-danger"> <h1 class="text-danger">
<span class="glyphicon glyphicon-heart" aria-hidden="true"></span> Health <span class="glyphicon glyphicon-heart" aria-hidden="true"></span> Health
</h1> </h1>
<ul class="list-group">
<li class="list-group-item"> <div class="row">
<span>Average response time sec :</span><span class="badge">{{healthCtrl.health.average_response_time_sec}}</span>
</li> <div class="col-md-6">
<li class="list-group-item"> <div>
<span>Average response time :</span><span class="badge">{{healthCtrl.health.average_response_time}}</span> <nvd3 options="healthCtrl.graph.averageResponseTime.options" data="healthCtrl.graph.averageResponseTime.data" api="healthCtrl.graph.averageResponseTime.api"></nvd3>
</li> </div>
<li class="list-group-item"> <ul class="list-group">
<span>Total response time sec :</span><span class="badge">{{healthCtrl.health.total_response_time_sec}}</span> <li class="list-group-item">
</li> <span>Total response time :</span><span class="badge">{{healthCtrl.health.total_response_time}}</span>
<li class="list-group-item"> </li>
<span>Total response time :</span><span class="badge">{{healthCtrl.health.total_response_time}}</span> </ul>
</li> <ul class="list-group">
<li class="list-group-item"> <li class="list-group-item">
<span>Total count :</span><span class="badge">{{healthCtrl.health.total_count}}</span> <span>PID :</span><span class="badge">{{healthCtrl.health.pid}}</span>
</li> </li>
<li class="list-group-item"> <li class="list-group-item">
<span>PID :</span><span class="badge">{{healthCtrl.health.pid}}</span> <span>Uptime :</span><span class="badge">{{healthCtrl.health.uptime}}</span>
</li> </li>
<li class="list-group-item"> </ul>
<span>Uptime :</span><span class="badge">{{healthCtrl.health.uptime}}</span> </div>
</li>
<li class="list-group-item"> <div class="col-md-6">
<span>Uptime sec :</span><span class="badge">{{healthCtrl.health.uptime_sec}}</span> <div>
</li> <nvd3 options="healthCtrl.graph.totalStatusCodeCount.options" data="healthCtrl.graph.totalStatusCodeCount.data" api="healthCtrl.graph.totalStatusCodeCount.api"></nvd3>
<li class="list-group-item"> </div>
<span>Time :</span><span class="badge">{{healthCtrl.health.time}}</span> <ul class="list-group">
</li> <li class="list-group-item">
<li class="list-group-item"> <span>Total count :</span><span class="badge">{{healthCtrl.health.total_count}}</span>
<span>Unixtime :</span><span class="badge">{{healthCtrl.health.unixtime}}</span> </li>
</li> <li class="list-group-item">
<li class="list-group-item"> <span>Count :</span><span class="badge">{{healthCtrl.health.count}}</span>
<span>Status code count :</span><span class="badge">{{healthCtrl.health.status_code_count}}</span> </li>
</li> </ul>
<li class="list-group-item"> </div>
<span>Total status code count :</span><span class="badge">{{healthCtrl.health.total_status_code_count}}</span>
</li> </div>
<li class="list-group-item">
<span>Count :</span><span class="badge">{{healthCtrl.health.count}}</span>
</li>
</ul>
</div> </div>

View file

@ -5,6 +5,7 @@
.module('traefik.section', [ .module('traefik.section', [
'ui.router', 'ui.router',
'ui.bootstrap', 'ui.bootstrap',
'nvd3',
'traefik.section.providers', 'traefik.section.providers',
'traefik.section.health' 'traefik.section.health'
]); ]);

View file

@ -20,6 +20,7 @@
"bootstrap": "~3.3.5", "bootstrap": "~3.3.5",
"angular-resource": "~1.4.7", "angular-resource": "~1.4.7",
"angular-ui-router": "~0.2.15", "angular-ui-router": "~0.2.15",
"angular-bootstrap": "~0.13.4" "angular-bootstrap": "~0.13.4",
"angular-nvd3": "~1.0.2"
} }
} }

File diff suppressed because one or more lines are too long

5
static/bower_components/d3/d3.min.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -13,6 +13,9 @@
<link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap-theme.min.css"> <link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap-theme.min.css">
<link rel="stylesheet" href="bower_components/angular-bootstrap/ui-bootstrap-csp.css"> <link rel="stylesheet" href="bower_components/angular-bootstrap/ui-bootstrap-csp.css">
<!-- NVD3 -->
<link rel="stylesheet" href="bower_components/nvd3/build/nv.d3.min.css">
<link rel="stylesheet" href="style.css"> <link rel="stylesheet" href="style.css">
</head> </head>
@ -57,6 +60,9 @@
<script src="bower_components/angular-resource/angular-resource.min.js"></script> <script src="bower_components/angular-resource/angular-resource.min.js"></script>
<script src="bower_components/angular-ui-router/release/angular-ui-router.min.js"></script> <script src="bower_components/angular-ui-router/release/angular-ui-router.min.js"></script>
<script src="bower_components/angular-bootstrap/ui-bootstrap-tpls.min.js"></script> <script src="bower_components/angular-bootstrap/ui-bootstrap-tpls.min.js"></script>
<script src="bower_components/d3/d3.min.js"></script>
<script src="bower_components/nvd3/build/nv.d3.min.js"></script>
<script src="bower_components/angular-nvd3/dist/angular-nvd3.min.js"></script>
<!-- end vendors --> <!-- end vendors -->
<script src="app/traefik.js"></script> <script src="app/traefik.js"></script>

View file

@ -26,4 +26,7 @@ Do `npm install` and `bower install`
- [UI Router - Documentation](https://github.com/angular-ui/ui-router/wiki) - [UI Router - Documentation](https://github.com/angular-ui/ui-router/wiki)
- [Bootstrap](http://getbootstrap.com) - [Bootstrap](http://getbootstrap.com)
- [Angular Bootstrap](https://angular-ui.github.io/bootstrap) - [Angular Bootstrap](https://angular-ui.github.io/bootstrap)
- [D3](http://d3js.org)
- [D3 - Documentation](https://github.com/mbostock/d3/wiki)
- [NVD3](http://nvd3.org)
- [Angular nvD3](http://krispo.github.io/angular-nvd3)