Stats improvements

This commit is contained in:
Vincent Fiduccia 2015-09-14 17:13:57 -07:00
parent c3182bfdad
commit c5c1ae27dd
9 changed files with 135 additions and 83 deletions

View File

@ -4,6 +4,8 @@ import { formatPercent, formatMib, formatKbps } from 'ui/utils/util';
const MAX_POINTS = 60;
const TICK_COUNT = 6;
const COLORS = ["#1f77b4", "#ff7f0e", "#2ca02c", "#d62728", "#9467bd", "#8c564b", "#e377c2", "#7f7f7f", "#bcbd22", "#17becf"];
const ALT_COLORS = ["#ff7f0e", "#1f77b4", "#2ca02c", "#d62728", "#9467bd", "#8c564b", "#e377c2", "#7f7f7f", "#bcbd22", "#17becf"];
export default Ember.Component.extend({
model: null,
@ -119,10 +121,10 @@ export default Ember.Component.extend({
{
if ( this.get('single') )
{
row = getOrCreateDataRow(graph, data, 'User');
row.push(point.cpu_user);
row = getOrCreateDataRow(graph, data, 'System');
row.push(point.cpu_system);
row = getOrCreateDataRow(graph, data, 'User');
row.push(point.cpu_user);
}
else
{
@ -166,10 +168,10 @@ export default Ember.Component.extend({
{
if ( this.get('single') )
{
row = getOrCreateDataRow(graph, data, 'Receive');
row.push(point.net_rx_kb);
row = getOrCreateDataRow(graph, data, 'Transmit');
row.push(point.net_tx_kb);
row = getOrCreateDataRow(graph, data, 'Receive');
row.push(point.net_rx_kb);
}
else
{
@ -185,10 +187,10 @@ export default Ember.Component.extend({
{
if ( this.get('single') )
{
row = getOrCreateDataRow(graph, data, 'Read');
row.push(point.disk_read_kb);
row = getOrCreateDataRow(graph, data, 'Write');
row.push(point.disk_write_kb);
row = getOrCreateDataRow(graph, data, 'Read');
row.push(point.disk_read_kb);
}
else
{
@ -222,11 +224,13 @@ export default Ember.Component.extend({
size: {
height: 110,
},
color: { pattern: ALT_COLORS.slice() },
data: {
type: 'area-step',
x: 'x',
columns: this.get('cpuData'),
groups: [[]], // Stacked graph, populated by getOrCreateDataRow...
order: null,
},
transition: { duration: 0 },
legend: { show: false },
@ -280,6 +284,7 @@ export default Ember.Component.extend({
size: {
height: 110,
},
color: { pattern: COLORS.slice() },
data: {
type: 'area-step',
x: 'x',
@ -337,11 +342,13 @@ export default Ember.Component.extend({
size: {
height: 110,
},
color: { pattern: ALT_COLORS.slice() },
data: {
type: 'area-step',
x: 'x',
columns: this.get('storageData'),
groups: [[]], // Stacked graph, populated by getOrCreateDataRow...
order: null,
},
transition: { duration: 0 },
legend: { show: false },
@ -393,11 +400,13 @@ export default Ember.Component.extend({
size: {
height: 110,
},
color: { pattern: ALT_COLORS.slice() },
data: {
type: 'area-step',
x: 'x',
columns: this.get('networkData'),
groups: [[]], // Stacked graph, populated by getOrCreateDataRow...
order: null,
},
transition: { duration: 0 },
legend: { show: false },

View File

@ -95,7 +95,7 @@ export default Ember.Component.extend({
update: function() {
var svg = this.get('svg');
var data = this.get('data').slice();
var data = (this.get('data')||[]).slice();
var x = this.get('x');
var y = this.get('y');
var line = this.get('line');

View File

@ -3,6 +3,8 @@ import Sortable from 'ui/mixins/sortable';
import ContainerSparkStats from 'ui/mixins/container-spark-stats';
export default Ember.Controller.extend(Sortable, ContainerSparkStats, {
statsSocket: null,
sortableContent: Ember.computed.alias('model.instances'),
sortBy: 'name',
sorts: {

View File

@ -1,4 +1,6 @@
import Ember from 'ember';
import Resource from 'ember-api-store/models/resource';
import { formatMib } from 'ui/utils/util';
var Host = Resource.extend({
type: 'host',
@ -53,12 +55,13 @@ var Host = Resource.extend({
}.property('physicalHostId'),
osBlurb: function() {
// @TODO this always sends back Ubuntu
if ( false && this.get('info.osInfo') )
if ( this.get('info.osInfo.operatingSystem') )
{
return this.get('info.osInfo.distribution') + ' ' + this.get('info.osInfo.version');
return this.get('info.osInfo.operatingSystem').replace(/\s+\(.*?\)/,'');
}
}.property('info.osInfo.{distribution,version}'),
}.property('info.osInfo.operatingSystem'),
osDetail: Ember.computed.alias('info.osInfo.operatingSystem'),
dockerBlurb: function() {
// @TODO this always sends back Ubuntu
@ -84,28 +87,53 @@ var Host = Resource.extend({
}
}.property('info.cpuInfo.{count,mhz}'),
cpuTooltip: Ember.computed.alias('info.cpuInfo.modelName'),
memoryBlurb: function() {
if ( this.get('info.memoryInfo') )
{
var gb = Math.round((this.get('info.memoryInfo.memTotal')/1024)*100)/100;
return gb + ' GiB';
return formatMib(this.get('info.memoryInfo.memTotal'));
}
}.property('info.memoryInfo.memTotal'),
diskBlurb: function() {
if ( this.get('info.diskInfo.mountPoints') )
{
var totalMb = 0;
// New hotness
if ( this.get('info.diskInfo.fileSystems') )
{
var fses = this.get('info.diskInfo.fileSystems')||[];
Object.keys(fses).forEach((fs) => {
totalMb += fses[fs].capacity;
});
return formatMib(totalMb);
}
else if ( this.get('info.diskInfo.mountPoints') )
{
// Old & busted
var mounts = this.get('info.diskInfo.mountPoints')||[];
Object.keys(mounts).forEach((mountPoint) => {
totalMb += mounts[mountPoint].total;
});
var gb = Math.round((totalMb/1024)*10)/10;
return gb + ' GiB';
return formatMib(totalMb);
}
}.property('info.diskInfo.mountPoints.@each.total'),
}.property('info.diskInfo.mountPoints.@each.total','info.diskInfo.fileSystems.@each.capacity'),
diskDetail: function() {
// New hotness
if ( this.get('info.diskInfo.fileSystems') )
{
var out = [];
var fses = this.get('info.diskInfo.fileSystems')||[];
Object.keys(fses).forEach((fs) => {
out.pushObject(Ember.Object.create({label: fs, value: formatMib(fses[fs].capacity)}));
});
return out;
}
}.property('info.diskInfo.fileSystems.@each.capacity'),
});
Host.reopenClass({

View File

@ -39,7 +39,7 @@
{{#if model.cpuBlurb}}
<li>
<label>CPU</label>
{{model.cpuBlurb}}
{{model.cpuBlurb}}{{#if model.cpuTooltip}} <i class="icon icon-info" tooltip="{{model.cpuTooltip}}"></i>{{/if}}
</li>
{{/if}}
@ -53,14 +53,20 @@
{{#if model.diskBlurb}}
<li>
<label>Storage</label>
{{model.diskBlurb}}
{{#if model.diskDetail}}
{{#each model.diskDetail as |disk|}}
<span style="display: inline-block; padding-right: 10px;">{{disk.value}} <i class="icon icon-info" tooltip="{{disk.label}}"></i></span>
{{/each}}
{{else}}
{{model.diskBlurb}} (total)
{{/if}}
</li>
{{/if}}
{{#if model.osBlurb}}
{{#if model.osDetail}}
<li>
<label>OS</label>
{{model.osBlurb}}
{{model.osDetail}}
</li>
{{/if}}

View File

@ -1,17 +1,8 @@
import Ember from 'ember';
const MAX_POINTS = 60;
const keys = ['cpu','memory','network','storage'];
export default Ember.Mixin.create({
init() {
this._super();
keys.forEach((key) => {
this.set(key+'Data', Ember.Object.create());
this.set(key+'Max', 0);
});
},
cpuData: null,
memoryData: null,
networkData: null,
@ -85,13 +76,20 @@ export default Ember.Mixin.create({
getOrCreateDataRow(key, id) {
var data = this.get(key+'Data');
var row = data[id];
if ( !data )
{
data = Ember.Object.create();
this.set(key+'Max', 0);
this.set(key+'Data', data);
}
var row = data.get(id);
if ( !row )
{
row = [];
for ( var i = 0 ; i < MAX_POINTS ; i++ )
{
row.push(0);
row.pushObject(0);
}
data.set(id,row);
}

View File

@ -117,7 +117,9 @@ export default Ember.Object.extend(Ember.Evented, {
if ( prev )
{
// Don't use `ts` here, need the unrounded time to get accurate CPU usage
var time_diff_ns = (tsFromString(data.timestamp) - tsFromString(prev.timestamp))*1e6;
var time_diff_ms = (tsFromString(data.timestamp) - tsFromString(prev.timestamp));
var time_diff_ns = time_diff_ms*1e6;
var time_diff_s = time_diff_ms/1000;
var count = 1;
// CPU
@ -135,6 +137,37 @@ export default Ember.Object.extend(Ember.Evented, {
out.cpu_total = toPercent((data.cpu.usage.total - prev.cpu.usage.total )/time_diff_ns);
out.cpu_count = count;
}
if ( data.diskio && data.diskio.io_service_bytes )
{
var read = 0;
var write = 0;
data.diskio.io_service_bytes.forEach((io) => {
if ( io && io.stats )
{
read += io.stats.Read || 0;
write += io.stats.Write || 0;
}
});
prev.diskio.io_service_bytes.forEach((io) => {
if ( io && io.stats )
{
read -= io.stats.Read || 0;
write -= io.stats.Write || 0;
}
});
out.disk_read_kb = read/(time_diff_s*1024);
out.disk_write_kb = write/(time_diff_s*1024);
}
// network
if ( data.network )
{
out.net_rx_kb = (data.network.rx_bytes - prev.network.rx_bytes)/(time_diff_s*1024);
out.net_tx_kb = (data.network.tx_bytes - prev.network.tx_bytes)/(time_diff_s*1024);
}
}
// Memory
@ -155,40 +188,6 @@ export default Ember.Object.extend(Ember.Evented, {
}
}
// Storage
if ( prev )
{
if ( data.diskio && data.diskio.io_serviced )
{
var read = 0;
var write = 0;
data.diskio.io_serviced.forEach((io) => {
if ( io && io.stats )
{
read += io.stats.Read || 0;
write += io.stats.Write || 0;
}
});
prev.diskio.io_serviced.forEach((io) => {
if ( io && io.stats )
{
read -= io.stats.Read || 0;
write -= io.stats.Write || 0;
}
});
out.disk_read_kb = read;
out.disk_write_kb = write;
}
}
// network
if ( data.network )
{
out.net_rx_kb = Math.round(data.network.rx_bytes/1000);
out.net_tx_kb = Math.round(data.network.tx_bytes/1000);
}
this.get('prev')[key] = data;
this.trigger('dataPoint', out);

View File

@ -89,11 +89,20 @@ export default Ember.Object.extend(Ember.Evented, {
this.setProperties({
connected: true,
tries: 0,
disconnectedAt: null,
});
this.trigger('connected', this.get('tries'), after);
// Don't reset tries for a little bit, in case the socket immediately closes again.
// This prevents open/imediate close loops from hammering the server because the tries count is never incrementing.
Ember.run.later(this, '_resetTries', 1000);
},
_resetTries: function() {
if ( this.get('connected') ) {
this.set('tries', 0);
}
},
_message: function(event) {

View File

@ -1,27 +1,28 @@
{
"name": "ui",
"dependencies": {
"async": "~0.9.2",
"bootstrap-multiselect": "~0.9.10",
"bootstrap-sass-official": "~3.3.1",
"c3": "~0.4.10",
"dagre": "~0.7.1",
"dagre-d3": "~0.4.3",
"ember": "1.13.3",
"jquery": "^2.1.4",
"ember-data": "1.13.5",
"ember-resolver": "~0.1.18",
"loader.js": "ember-cli/loader.js#3.2.0",
"ember-cli-shims": "ember-cli/ember-cli-shims#0.0.3",
"ember-cli-test-loader": "ember-cli-test-loader#0.1.3",
"ember-data": "1.13.5",
"ember-load-initializers": "ember-cli/ember-load-initializers#0.1.5",
"ember-qunit": "0.4.1",
"ember-qunit-notifications": "0.0.7",
"qunit": "~1.17.1",
"ember-resolver": "~0.1.18",
"font-awesome": "~4.4.0",
"jgrowl": "~1.4.2",
"c3": "~0.4.10",
"jquery": "^2.1.4",
"jquery.cookie": "~1.4.1",
"bootstrap-sass-official": "~3.3.1",
"bootstrap-multiselect": "~0.9.10",
"zeroclipboard": "~2.2.0",
"loader.js": "ember-cli/loader.js#3.2.0",
"position-calculator": "~1.1.2",
"prism": "gh-pages",
"dagre": "~0.7.1",
"dagre-d3": "~0.4.3",
"async": "~0.9.2",
"position-calculator": "~1.1.2"
"qunit": "~1.17.1",
"zeroclipboard": "~2.2.0"
}
}