%PDF- %PDF-
Direktori : /data/old/opt/luameter/ |
Current File : //data/old/opt/luameter/luameter.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>