Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UI: Use stats trackers for resource rows #4726

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 18 additions & 13 deletions ui/app/components/allocation-row.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@ import Ember from 'ember';
import { inject as service } from '@ember/service';
import Component from '@ember/component';
import { computed } from '@ember/object';
import { alias } from '@ember/object/computed';
import { run } from '@ember/runloop';
import { lazyClick } from '../helpers/lazy-click';
import { task, timeout } from 'ember-concurrency';
import { lazyClick } from '../helpers/lazy-click';
import AllocationStatsTracker from 'nomad-ui/utils/classes/allocation-stats-tracker';

export default Component.extend({
store: service(),
token: service(),

tagName: 'tr',

Expand All @@ -18,14 +21,21 @@ export default Component.extend({
// Used to determine whether the row should mention the node or the job
context: null,

backoffSequence: computed(() => [500, 800, 1300, 2100, 3400, 5500]),

// Internal state
stats: null,
statsError: false,

enablePolling: computed(() => !Ember.testing),

stats: computed('allocation', function() {
return AllocationStatsTracker.create({
fetch: url => this.get('token').authorizedRequest(url),
allocation: this.get('allocation'),
});
}),

cpu: alias('stats.cpu.lastObject'),
memory: alias('stats.memory.lastObject'),

onClick() {},

click(event) {
Expand All @@ -39,31 +49,26 @@ export default Component.extend({
run.scheduleOnce('afterRender', this, qualifyAllocation);
} else {
this.get('fetchStats').cancelAll();
this.set('stats', null);
}
},

fetchStats: task(function*(allocation) {
const backoffSequence = this.get('backoffSequence').slice();
const maxTiming = backoffSequence.pop();

fetchStats: task(function*() {
do {
try {
const stats = yield allocation.fetchStats();
this.set('stats', stats);
yield this.get('stats.poll').perform();
this.set('statsError', false);
} catch (error) {
this.set('statsError', true);
}
yield timeout(backoffSequence.shift() || maxTiming);
yield timeout(500);
} while (this.get('enablePolling'));
}).drop(),
});

function qualifyAllocation() {
const allocation = this.get('allocation');
return allocation.reload().then(() => {
this.get('fetchStats').perform(allocation);
this.get('fetchStats').perform();

// Make sure that the job record in the store for this allocation
// is complete and not a partial from the list endpoint
Expand Down
64 changes: 64 additions & 0 deletions ui/app/components/task-row.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import Ember from 'ember';
import Component from '@ember/component';
import { inject as service } from '@ember/service';
import { computed } from '@ember/object';
import { alias } from '@ember/object/computed';
import { task, timeout } from 'ember-concurrency';
import { lazyClick } from '../helpers/lazy-click';

export default Component.extend({
store: service(),
token: service(),
statsTrackersRegistry: service('stats-trackers-registry'),

tagName: 'tr',
classNames: ['task-row', 'is-interactive'],

task: null,

// Internal state
statsError: false,

enablePolling: computed(() => !Ember.testing),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couple of question on this for my own benefit really:

  1. Could you use alias for this?
  2. Does Ember.testing ever change once things are running?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alias only works for paths on the object already (e.g., this.Ember.testing), so no.

I just tried it and yes, Ember.testing can be changed at runtime, but it never happens from framework code.


// Since all tasks for an allocation share the same tracker, use the registry
stats: computed('task', function() {
return this.get('statsTrackersRegistry').getTracker(this.get('task.allocation'));
}),

taskStats: computed('task.name', 'stats.tasks.[]', function() {
const ret = this.get('stats.tasks').findBy('task', this.get('task.name'));
return ret;
}),

cpu: alias('taskStats.cpu.lastObject'),
memory: alias('taskStats.memory.lastObject'),

onClick() {},

click(event) {
lazyClick([this.get('onClick'), event]);
},

fetchStats: task(function*() {
do {
try {
yield this.get('stats.poll').perform();
this.set('statsError', false);
} catch (error) {
this.set('statsError', true);
}
yield timeout(500);
} while (this.get('enablePolling'));
}).drop(),

didReceiveAttrs() {
const allocation = this.get('task.allocation');

if (allocation) {
this.get('fetchStats').perform();
} else {
this.get('fetchStats').cancelAll();
}
},
});
13 changes: 0 additions & 13 deletions ui/app/models/allocation.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { belongsTo } from 'ember-data/relationships';
import { fragment, fragmentArray } from 'ember-data-model-fragments/attributes';
import intersection from 'lodash.intersection';
import shortUUIDProperty from '../utils/properties/short-uuid';
import AllocationStats from '../utils/classes/allocation-stats';

const STATUS_ORDER = {
pending: 1,
Expand Down Expand Up @@ -74,18 +73,6 @@ export default Model.extend({
return [];
}),

fetchStats() {
return this.get('token')
.authorizedRequest(`/v1/client/allocation/${this.get('id')}/stats`)
.then(res => res.json())
.then(json => {
return new AllocationStats({
stats: json,
allocation: this,
});
});
},

states: fragmentArray('task-state'),
rescheduleEvents: fragmentArray('reschedule-event'),

Expand Down
50 changes: 6 additions & 44 deletions ui/app/templates/allocations/allocation/index.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -50,52 +50,14 @@
<th>Last Event</th>
{{#t.sort-by prop="events.lastObject.time"}}Time{{/t.sort-by}}
<th>Addresses</th>
<th>CPU</th>
<th>Memory</th>
{{/t.head}}
{{#t.body as |row|}}
<tr
data-test-task-row={{row.model.task.name}}
onclick={{action "taskClick" row.model.allocation row.model}}
class="is-interactive">
<td class="is-narrow">
{{#if (not row.model.driverStatus.healthy)}}
<span data-test-icon="unhealthy-driver" class="tooltip text-center" aria-label="{{row.model.driver}} is unhealthy">
{{x-icon "warning" class="is-warning"}}
</span>
{{/if}}
</td>
<td data-test-name>
{{#link-to "allocations.allocation.task" row.model.allocation row.model class="is-primary"}}
{{row.model.name}}
{{/link-to}}
</td>
<td data-test-state>{{row.model.state}}</td>
<td data-test-message>
{{#if row.model.events.lastObject.message}}
{{row.model.events.lastObject.message}}
{{else}}
<em>No message</em>
{{/if}}
</td>
<td data-test-time>{{moment-format row.model.events.lastObject.time "MM/DD/YY HH:mm:ss"}}</td>
<td data-test-ports>
<ul>
{{#with row.model.resources.networks.firstObject as |network|}}
{{#each network.reservedPorts as |port|}}
<li data-test-port>
<strong>{{port.Label}}:</strong>
<a href="http://{{network.ip}}:{{port.Value}}" target="_blank">{{network.ip}}:{{port.Value}}</a>
</li>
{{/each}}
{{#each network.dynamicPorts as |port|}}
<li>
<strong>{{port.Label}}:</strong>
<a href="http://{{network.ip}}:{{port.Value}}" target="_blank">{{network.ip}}:{{port.Value}}</a>
</li>
{{/each}}
{{/with}}
</ul>
</td>
</tr>
{{task-row
data-test-task-row=row.model.name
task=row.model
onClick=(action "taskClick" row.model.allocation row.model)}}
{{/t.body}}
{{/list-table}}
</div>
Expand Down
24 changes: 12 additions & 12 deletions ui/app/templates/components/allocation-row.hbs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
<td data-test-indicators class="is-narrow">
{{#if allocation.unhealthyDrivers.length}}
<span data-test-icon="unhealthy-driver" class="tooltip text-center" aria-label="Allocation depends on unhealthy drivers">
<span data-test-icon="unhealthy-driver" class="tooltip text-center" role="tooltip" aria-label="Allocation depends on unhealthy drivers">
{{x-icon "warning" class="is-warning"}}
</span>
{{/if}}
{{#if allocation.nextAllocation}}
<span data-test-icon="reschedule" class="tooltip text-center" aria-label="Allocation was rescheduled">
<span data-test-icon="reschedule" class="tooltip text-center" role="tooltip" aria-label="Allocation was rescheduled">
{{x-icon "history" class="is-faded"}}
</span>
{{/if}}
Expand Down Expand Up @@ -42,41 +42,41 @@
<td data-test-job-version class="is-1">{{allocation.jobVersion}}</td>
{{/if}}
<td data-test-cpu class="is-1 has-text-centered">
{{#if (and (not stats) fetchStats.isRunning)}}
{{#if (and (not cpu) fetchStats.isRunning)}}
...
{{else if (not allocation)}}
{{! nothing when there's no allocation}}
{{else if statsError}}
<span class="tooltip text-center" aria-label="Couldn't collect stats">
<span class="tooltip text-center" role="tooltip" aria-label="Couldn't collect stats">
{{x-icon "warning" class="is-warning"}}
</span>
{{else}}
<div class="inline-chart is-small tooltip" aria-label="{{stats.cpuUsed}} / {{stats.reservedCPU}} MHz">
<div class="inline-chart is-small tooltip" role="tooltip" aria-label="{{cpu.used}} / {{stats.reservedCPU}} MHz">
<progress
class="progress is-info is-small"
value="{{stats.percentCPU}}"
value="{{cpu.percent}}"
max="1">
{{stats.percentCPU}}
{{cpu.percent}}
</progress>
</div>
{{/if}}
</td>
<td data-test-mem class="is-1 has-text-centered">
{{#if (and (not stats) fetchStats.isRunning)}}
{{#if (and (not memory) fetchStats.isRunning)}}
...
{{else if (not allocation)}}
{{! nothing when there's no allocation}}
{{else if statsError}}
<span class="tooltip is-small text-center" aria-label="Couldn't collect stats">
<span class="tooltip is-small text-center" role="tooltip" aria-label="Couldn't collect stats">
{{x-icon "warning" class="is-warning"}}
</span>
{{else}}
<div class="inline-chart tooltip" aria-label="{{format-bytes stats.memoryUsed}} / {{stats.reservedMemory}} MiB">
<div class="inline-chart tooltip" role="tooltip" aria-label="{{format-bytes memory.used}} / {{stats.reservedMemory}} MiB">
<progress
class="progress is-danger is-small"
value="{{stats.percentMemory}}"
value="{{memory.percent}}"
max="1">
{{stats.percentMemory}}
{{memory.percent}}
</progress>
</div>
{{/if}}
Expand Down
2 changes: 1 addition & 1 deletion ui/app/templates/components/client-node-row.hbs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<td data-test-icon class="is-narrow">
{{#if node.unhealthyDrivers.length}}
<span class="tooltip text-center" aria-label="Client has unhealthy drivers">
<span class="tooltip text-center" role="tooltip" aria-label="Client has unhealthy drivers">
{{x-icon "warning" class="is-warning"}}
</span>
{{/if}}
Expand Down
12 changes: 6 additions & 6 deletions ui/app/templates/components/freestyle/sg-progress-bar.hbs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{{#freestyle-usage "progress-bar" title="Progress Bar"}}
<div class="inline-chart tooltip" aria-label="5 / 15">
<div class="inline-chart tooltip" role="tooltip" aria-label="5 / 15">
<progress
class="progress is-primary is-small"
value="0.33"
Expand All @@ -12,7 +12,7 @@
{{#freestyle-usage "progress-bar-colors" title="Progress Bar Colors"}}
<div class="columns">
<div class="column">
<div class="inline-chart tooltip" aria-label="5 / 15">
<div class="inline-chart tooltip" role="tooltip" aria-label="5 / 15">
<progress
class="progress is-info is-small"
value="0.33"
Expand All @@ -22,7 +22,7 @@
</div>
</div>
<div class="column">
<div class="inline-chart tooltip" aria-label="5 / 15">
<div class="inline-chart tooltip" role="tooltip" aria-label="5 / 15">
<progress
class="progress is-success is-small"
value="0.33"
Expand All @@ -32,7 +32,7 @@
</div>
</div>
<div class="column">
<div class="inline-chart tooltip" aria-label="5 / 15">
<div class="inline-chart tooltip" role="tooltip" aria-label="5 / 15">
<progress
class="progress is-warning is-small"
value="0.33"
Expand All @@ -42,7 +42,7 @@
</div>
</div>
<div class="column">
<div class="inline-chart tooltip" aria-label="5 / 15">
<div class="inline-chart tooltip" role="tooltip" aria-label="5 / 15">
<progress
class="progress is-danger is-small"
value="0.33"
Expand All @@ -57,7 +57,7 @@
{{#freestyle-usage "progress-bar-live" title="Progress Bar Live Updates"}}
<div class="columns">
<div class="column is-one-third">
<div class="inline-chart tooltip" aria-label="{{numerator}} / {{denominator}}">
<div class="inline-chart tooltip" role="tooltip" aria-label="{{numerator}} / {{denominator}}">
<progress
class="progress is-primary is-small"
value="{{percentage}}"
Expand Down
Loading