%PDF- %PDF-
| Direktori : /data/old/opt/luameter/ |
| Current File : //data/old/opt/luameter/index.html |
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>Nginx Stats - by Luameter</title>
<link rel="stylesheet" href="vendor/tables-min.css">
<style>
h1, h2, h3, h4, h5 {
font-weight: 400;
}
h3 {
font-style: italic;
}
html {
font-family: sans-serif;
font-size: 13px;
color: rgb(75, 75, 75);
}
a {
color: rgb(75, 75, 75);
text-decoration: none;
}
.main {
padding: 20px;
}
.sub-head {
font-size: 50%;
color: #777;
}
.tooltip {
text-align: left;
border-bottom: 1px #999 dotted;
display: inline;
position: relative;
cursor: help;
}
.tooltip:hover:after {
background: #4b4b4b;
bottom: 26px;
color: #fff;
content: attr(title);
left: 20%;
padding: 5px 15px;
position: absolute;
z-index: 98;
width: 10em;
white-space: pre-line;
}
.tooltip:hover:before {
border: solid;
border-color: #4b4b4b transparent;
border-width: 6px 6px 0 6px;
bottom: 20px;
content: "";
left: 50%;
position: absolute;
z-index: 99;
}
</style>
</head>
<body>
<div class="main">
<div id="stats">
<h1><a href="http://luameter.com">Luameter<a></h1>
</div>
</div>
<script id="stats-template" type="text/x-handlebars-template">
<h1><a href="http://luameter.com">Luameter</a> <span class="sub-head">{{ luameter_version }}</span></h1>
<h2>Server</h2>
<table class="pure-table">
<thead>
<tr>
<th rowspan="2">Nginx</th>
<th rowspan="2">Ngx_lua</th>
<th rowspan="2">Uptime</th>
<!--<th>Timestamp</th>-->
<th colspan="4">Connections</th>
</tr>
<tr>
<th>Active</th>
<th>Reading</th>
<th>Writing</th>
<th>Waiting</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{ nginx_version }}</td>
<td>{{ ngx_lua_version }}</td>
<td>{{ uptime uptime }}</td>
<!--<td>{{ timestamp }}</td>-->
<td>{{ connections.active }}</td>
<td>{{ connections.reading }}</td>
<td>{{ connections.writing }}</td>
<td>{{ connections.waiting }}</td>
</tr>
</tbody>
</table>
<h2>Zone</h2>
<table class="pure-table pure-table-striped">
<thead>
<tr>
<th rowspan="2">Zone</th>
<th colspan="3">Requests</th>
<th colspan="6">Responses</th>
<th colspan="3">Latency (ms)</th>
<th colspan="2">Traffic</th>
<th colspan="3">Cache</th>
</tr>
<tr>
<th>Rate (r/s)</th>
<th>Moving Avg (r/s)</th>
<th>Total</th>
<th>1xx</th>
<th>2xx</th>
<th>3xx</th>
<th>4xx</th>
<th>5xx</th>
<th>Total</th>
<th>Mean</th>
<th>P90</th>
<th>P99</th>
<th>Received</th>
<th>Sent</th>
<th>Hit</th>
<th>Miss</th>
<th>Expired</th>
</tr>
</thead>
<tbody>
{{#each_in_order zones}}{{#with this}}
<tr>
<td>{{ name }}</td>
<td>
<span class="line">{{ requests_per_sec_history }}</span>
{{ round requests_per_sec 0 }}
</td>
<td>
<span class="bar">
{{ round rates.one_minute_avg }},
{{ round rates.five_minute_avg }},
{{ round rates.fifteen_minute_avg}}
</span>
{{ round rates.one_minute_avg }}
·
{{ round rates.five_minute_avg }}
·
{{ round rates.fifteen_minute_avg }}
</td>
<td>{{ requests }}</td>
<td>
<a class="tooltip" title="{{ responses.[1xx_details] }}">
{{ responses.[1xx] }}
</a>
</td>
<td>
<a class="tooltip" title="{{ responses.[2xx_details] }}">
{{ responses.[2xx] }}
</a>
</td>
<td>
<a class="tooltip" title="{{ responses.[3xx_details] }}">
{{ responses.[3xx] }}
</a>
</td>
<td>
<a class="tooltip" title="{{ responses.[4xx_details] }}">
{{ responses.[4xx] }}
</a>
</td>
<td>
<a class="tooltip" title="{{ responses.[5xx_details] }}">
{{ responses.[5xx] }}
</a>
</td>
<td>
{{ responses.total }}
</td>
<td>{{ round latency.mean 1 }}</td>
<td>{{ round latency.p90 1 }}</td>
<td>{{ round latency.p99 1 }}</td>
<td>
<a class="tooltip" title="Total: {{ bytes received }}">
{{ bytes received_per_sec }}/s
</a>
</td>
<td>
<a class="tooltip" title="Total: {{ bytes sent }}">
{{ bytes sent_per_sec }}/s
</a>
</td>
<td>
<a class="tooltip" title="Hit Ratio: {{ round cache.hit_ratio }}">
{{ cache.hit }}
</a>
</td>
<td>
<a class="tooltip" title="Miss Ratio: {{ round cache.miss_ratio }}">
{{ cache.miss }}
</a>
</td>
<td>
<a class="tooltip" title="Expired Ratio: {{ round cache.expired_ratio }}">
{{ cache.expired }}
</a>
</td>
</tr>
{{/with}}{{/each_in_order}}
</tbody>
</table>
<h2>Upstream</h2>
<table class="pure-table pure-table-stripped">
<thead>
<tr>
<th rowspan="2">Upstream</th>
<th colspan="3">Requests</th>
<th colspan="6">Responses</th>
<th colspan="3">Latency (ms)</th>
<th colspan="2">Traffic</th>
</tr>
<tr>
<th>Rate (r/s)</th>
<th>Moving Avg</th>
<th>Total</th>
<th>1xx</th>
<th>2xx</th>
<th>3xx</th>
<th>4xx</th>
<th>5xx</th>
<th>Total</th>
<th>Mean</th>
<th>P90</th>
<th>P99</th>
<th>Received</th>
<th>Sent</th>
</tr>
</thead>
<tbody>
{{#each_in_order upstreams}}{{#with this}}
<tr>
<td>{{ name }}</td>
<td>
<span class="line">{{ requests_per_sec_history }}</span>
{{ round requests_per_sec 0 }}
</td>
<td>
<span class="bar">
{{ round rates.one_minute_avg }},
{{ round rates.five_minute_avg }},
{{ round rates.fifteen_minute_avg}}
</span>
{{ round rates.one_minute_avg }}
·
{{ round rates.five_minute_avg }}
·
{{ round rates.fifteen_minute_avg }}
</td>
<td>{{ requests }}</td>
<td>
<a class="tooltip" title="{{ responses.[1xx_details] }}">
{{ responses.[1xx] }}
</a>
</td>
<td>
<a class="tooltip" title="{{ responses.[2xx_details] }}">
{{ responses.[2xx] }}
</a>
</td>
<td>
<a class="tooltip" title="{{ responses.[3xx_details] }}">
{{ responses.[3xx] }}
</a>
</td>
<td>
<a class="tooltip" title="{{ responses.[4xx_details] }}">
{{ responses.[4xx] }}
</a>
</td>
<td>
<a class="tooltip" title="{{ responses.[5xx_details] }}">
{{ responses.[5xx] }}
</a>
</td>
<td>
{{ responses.total }}
</td>
<td>{{ round latency.mean 1 }}</td>
<td>{{ round latency.p90 1 }}</td>
<td>{{ round latency.p99 1 }}</td>
<td>
<a class="tooltip" title="Total: {{ bytes received }}">
{{ bytes received_per_sec }}/s
</a>
</td>
<td>
<a class="tooltip" title="Total: {{ bytes sent }}">
{{ bytes sent_per_sec }}/s
</a>
</td>
</tr>
{{/with}}{{/each_in_order}}
</tbody>
</table>
</script>
<script src="vendor/jquery.min.js"></script>
<script src="vendor/handlebars.min.js"></script>
<script src="vendor/jquery.peity.min.js"></script>
<script>
MAX_HISTORY = 60;
var all_stats = {};
var charts = {};
Handlebars.registerHelper('uptime', function(seconds) {
var days = seconds > 86400 ? Math.floor(seconds / 86400) + 'd ' : '';
var hours = seconds > 3600 ? Math.floor(seconds % 86400 / 3600) + 'h ' : '';
var minutes = seconds > 60 ? Math.floor(seconds % 3600 / 60) + 'm ' : '';
seconds = Math.floor(seconds % 60) + 's';
return days + hours + minutes + seconds;
});
Handlebars.registerHelper('each_in_order', function(context, options) {
var ret = "";
$.each(Object.keys(context).sort(), function(_, key) {
var ctx = context[key];
ctx['name'] = key;
ret = ret + options.fn(ctx);
});
return ret;
});
var round = function(num, decimals) {
num = num || 0;
decimals = parseInt(decimals);
if (isNaN(decimals)) {
decimals = 2;
if (num > 10) decimals = 1;
if (num > 100) decimals = 0;
}
return parseFloat(num).toFixed(decimals);
};
Handlebars.registerHelper('round', round);
Handlebars.registerHelper('bytes', function(bytes) {
if (!bytes) return '0 B';
if (bytes < 1024) return round(bytes, 0) + ' B';
var ki_bytes = round(bytes / 1024, 2);
if (ki_bytes < 1024) return ki_bytes + ' KiB';
var mi_bytes = round(ki_bytes / 1024, 2);
if (mi_bytes < 1024) return mi_bytes + ' MiB';
var gi_bytes = round(mi_bytes / 1024, 2);
if (gi_bytes < 1024) return gi_bytes + ' GiB';
var ti_bytes = round(gi_bytes / 1024, 2);
return ti_bytes + ' TiB';
});
var calc_data_rate = function(name, stats) {
var previous = all_stats[name];
if (previous == undefined) return;
var elapsed = stats.ts - previous.ts;
$.each(['requests', 'received', 'sent'], function(_, key) {
var diff = stats[key] - previous[key];
if (elapsed > 0) {
diff = diff / elapsed;
}
stats[key + '_per_sec'] = diff > 0 ? diff : 0;
});
$.each(['requests_per_sec'], function(_, key) {
var history = stats[key + '_history'] = previous[key + '_history'];
if (history == undefined) {
history = stats[key + '_history'] = [];
}
var len = history.push(stats[key]);
if (len > MAX_HISTORY) {
history.shift();
}
});
};
var calc_cache_ratio = function(stats) {
var total = stats['responses']['total'];
if (total > 0) {
$.each(['hit', 'miss', 'expired'], function (_, key) {
stats['cache'][key + '_ratio'] = stats['cache'][key] / total;
});
}
};
var template = Handlebars.compile($('#stats-template').html());
var update = function() {
$.getJSON('/stats', function(data) {
var calc_derived_stats = function(name, stats) {
stats.ts = data.timestamp;
calc_data_rate(name, stats);
calc_cache_ratio(stats);
for (var i = 1; i <= 5; i++) {
var statuses = [];
for (var j = 0; j < 100; j++) {
var status = 100 * i + j;
if (stats.responses[status] > 0) {
statuses.push(status + ': ' + stats.responses[status]);
}
}
if (statuses.length == 0) {
stats.responses[i + 'xx_details'] = '0';
} else {
stats.responses[i + 'xx_details'] = statuses.join('\x0A');
}
}
all_stats[name] = stats;
};
$.each(data.zones, calc_derived_stats);
$.each(data.upstreams, calc_derived_stats);
// update stats table
$('#stats').html(template(data));
$('.line').peity('line', {width: MAX_HISTORY, fill: '#e0e0e0', stroke: '#4b4b4b'});
$('.bar').peity('bar', {width: 18, fill: ['#6b6b6b']});
});
};
update();
setInterval(update, 10000);
</script>
</body>
</html>