mirror of https://github.com/rancher/ui.git
Stats improvements
This commit is contained in:
parent
c3182bfdad
commit
c5c1ae27dd
|
|
@ -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 },
|
||||
|
|
|
|||
|
|
@ -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');
|
||||
|
|
|
|||
|
|
@ -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: {
|
||||
|
|
|
|||
|
|
@ -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 totalMb = 0;
|
||||
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({
|
||||
|
|
|
|||
|
|
@ -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}}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
27
bower.json
27
bower.json
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue