commit
74c5562c2b
14 changed files with 289 additions and 67 deletions
|
@ -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
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 |
|
@ -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
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
@ -6,17 +6,195 @@
|
|||
|
||||
var vm = this;
|
||||
|
||||
vm.health = Health.get();
|
||||
vm.graph = {
|
||||
averageResponseTime: {},
|
||||
totalStatusCodeCount: {}
|
||||
}
|
||||
|
||||
var intervalId = $interval(function () {
|
||||
Health.get(function (health) {
|
||||
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;
|
||||
}, function (error) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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(loadData, erroData);
|
||||
}, 3000);
|
||||
|
||||
// Stop auto refresh when page change
|
||||
$scope.$on('$destroy', function () {
|
||||
$interval.cancel(intervalId);
|
||||
});
|
||||
|
|
|
@ -2,45 +2,42 @@
|
|||
<h1 class="text-danger">
|
||||
<span class="glyphicon glyphicon-heart" aria-hidden="true"></span> Health
|
||||
</h1>
|
||||
|
||||
<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>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>
|
||||
</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>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>
|
||||
<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>
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
.module('traefik.section', [
|
||||
'ui.router',
|
||||
'ui.bootstrap',
|
||||
'nvd3',
|
||||
'traefik.section.providers',
|
||||
'traefik.section.health'
|
||||
]);
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
1
static/bower_components/angular-nvd3/dist/angular-nvd3.min.js
vendored
Normal file
1
static/bower_components/angular-nvd3/dist/angular-nvd3.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
5
static/bower_components/d3/d3.min.js
vendored
Normal file
5
static/bower_components/d3/d3.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
static/bower_components/nvd3/build/nv.d3.min.css
vendored
Normal file
1
static/bower_components/nvd3/build/nv.d3.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
8
static/bower_components/nvd3/build/nv.d3.min.js
vendored
Normal file
8
static/bower_components/nvd3/build/nv.d3.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
|
@ -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>
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue