Merge pull request #43 from ldez/feature/health-graph

Health graph
This commit is contained in:
Vincent Demeester 2015-10-08 22:55:41 +02:00
commit 74c5562c2b
14 changed files with 289 additions and 67 deletions

View file

@ -72,7 +72,8 @@ Refer to the [benchmarks section](docs/index.md#benchmarks) in the documentation
You can access to a simple HTML frontend of Træfik.
![HTML frontend](docs/img/web.frontend.png)
![Web UI Providers](docs/img/web.frontend.png)
![Web UI Health](docs/img/traefik-health.png)
## Contributing

BIN
docs/img/traefik-health.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 53 KiB

View file

@ -232,26 +232,46 @@ address = ":8080"
* `/`: provides a simple HTML frontend of Træfik
![HTML frontend](img/web.frontend.png)
![Web UI Providers](img/web.frontend.png)
![Web UI Health](img/traefik-health.png)
* `/health`: `GET` json metrics
```sh
$ curl -s "http://localhost:8080/health" | jq .
{
"average_response_time_sec": 0,
"average_response_time": "0",
"total_response_time_sec": 0,
"total_response_time": "0",
"total_count": 0,
"pid": 12861,
"uptime": "7m12.80607635s",
"uptime_sec": 432.80607635,
"time": "2015-09-22 10:25:16.448023473 +0200 CEST",
"unixtime": 1442910316,
"status_code_count": {},
"total_status_code_count": {},
"count": 0
// Træfɪk PID
"pid": 2458,
// Træfɪk server uptime (formated time)
"uptime": "39m6.885931127s",
// Træfɪk server uptime in seconds
"uptime_sec": 2346.885931127,
// current server date
"time": "2015-10-07 18:32:24.362238909 +0200 CEST",
// current server date in seconds
"unixtime": 1444235544,
// count HTTP response status code in realtime
"status_code_count": {
"502": 1
},
// count HTTP response status code since Træfɪk started
"total_status_code_count": {
"200": 7,
"404": 21,
"502": 13
},
// count HTTP response
"count": 1,
// count HTTP response
"total_count": 41,
// sum of all response time (formated time)
"total_response_time": "35.456865605s",
// sum of all response time in seconds
"total_response_time_sec": 35.456865605,
// average response time (formated time)
"average_response_time": "864.8016ms",
// average response time in seconds
"average_response_time_sec": 0.8648016000000001
}
```

View file

@ -6,21 +6,199 @@
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 () {
Health.get(function (health) {
vm.health = health;
}, function (error) {
vm.health = {};
$log.error(error);
});
Health.get(loadData, erroData);
}, 3000);
// Stop auto refresh when page change
$scope.$on('$destroy', function () {
$interval.cancel(intervalId);
});
}]);
}]);
})();

View file

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

View file

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

View file

@ -1,7 +1,7 @@
{
"name": "traefik",
"version": "1.0.0",
"homepage": "https://github.com/ldez/traefik",
"homepage": "http://traefik.io",
"authors": [
"Fernandez Ludovic <ludovic.fernandez@zenika.com>"
],
@ -20,6 +20,7 @@
"bootstrap": "~3.3.5",
"angular-resource": "~1.4.7",
"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/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">
</head>
@ -57,6 +60,9 @@
<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-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 -->
<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)
- [Bootstrap](http://getbootstrap.com)
- [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)