Conditionally show utilization metrics on alloc and task rows

This commit is contained in:
Michael Lange 2018-12-10 15:25:48 -08:00
parent 0005b1fca2
commit 71a06a6b7f
7 changed files with 105 additions and 87 deletions

View file

@ -26,7 +26,9 @@ export default Component.extend({
enablePolling: computed(() => !Ember.testing),
stats: computed('allocation', function() {
stats: computed('allocation', 'allocation.isRunning', function() {
if (!this.get('allocation.isRunning')) return;
return AllocationStatsTracker.create({
fetch: url => this.get('token').authorizedRequest(url),
allocation: this.get('allocation'),
@ -54,12 +56,15 @@ export default Component.extend({
fetchStats: task(function*() {
do {
try {
yield this.get('stats.poll').perform();
this.set('statsError', false);
} catch (error) {
this.set('statsError', true);
if (this.get('stats')) {
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(),

View file

@ -22,13 +22,16 @@ export default Component.extend({
enablePolling: computed(() => !Ember.testing),
// Since all tasks for an allocation share the same tracker, use the registry
stats: computed('task', function() {
stats: computed('task', 'task.isRunning', function() {
if (!this.get('task.isRunning')) return;
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;
if (!this.get('stats')) return;
return this.get('stats.tasks').findBy('task', this.get('task.name'));
}),
cpu: alias('taskStats.cpu.lastObject'),
@ -42,12 +45,15 @@ export default Component.extend({
fetchStats: task(function*() {
do {
try {
yield this.get('stats.poll').perform();
this.set('statsError', false);
} catch (error) {
this.set('statsError', true);
if (this.get('stats')) {
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(),

View file

@ -42,42 +42,42 @@
<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 cpu) fetchStats.isRunning)}}
...
{{else if (not allocation)}}
{{! nothing when there's no allocation}}
{{else if statsError}}
<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" role="tooltip" aria-label="{{cpu.used}} / {{stats.reservedCPU}} MHz">
<progress
class="progress is-info is-small"
value="{{cpu.percent}}"
max="1">
{{cpu.percent}}
</progress>
</div>
{{#if allocation.isRunning}}
{{#if (and (not cpu) fetchStats.isRunning)}}
...
{{else if statsError}}
<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" role="tooltip" aria-label="{{cpu.used}} / {{stats.reservedCPU}} MHz">
<progress
class="progress is-info is-small"
value="{{cpu.percent}}"
max="1">
{{cpu.percent}}
</progress>
</div>
{{/if}}
{{/if}}
</td>
<td data-test-mem class="is-1 has-text-centered">
{{#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" role="tooltip" aria-label="Couldn't collect stats">
{{x-icon "warning" class="is-warning"}}
</span>
{{else}}
<div class="inline-chart tooltip" role="tooltip" aria-label="{{format-bytes memory.used}} / {{stats.reservedMemory}} MiB">
<progress
class="progress is-danger is-small"
value="{{memory.percent}}"
max="1">
{{memory.percent}}
</progress>
</div>
{{#if allocation.isRunning}}
{{#if (and (not memory) fetchStats.isRunning)}}
...
{{else if statsError}}
<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" role="tooltip" aria-label="{{format-bytes memory.used}} / {{stats.reservedMemory}} MiB">
<progress
class="progress is-danger is-small"
value="{{memory.percent}}"
max="1">
{{memory.percent}}
</progress>
</div>
{{/if}}
{{/if}}
</td>

View file

@ -38,42 +38,42 @@
</ul>
</td>
<td data-test-cpu class="is-1 has-text-centered">
{{#if (and (not cpu) fetchStats.isRunning)}}
...
{{else if (not task)}}
{{! nothing when there's no task}}
{{else if statsError}}
<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" role="tooltip" aria-label="{{cpu.used}} / {{taskStats.reservedCPU}} MHz">
<progress
class="progress is-info is-small"
value="{{cpu.percent}}"
max="1">
{{cpu.percent}}
</progress>
</div>
{{#if task.isRunning}}
{{#if (and (not cpu) fetchStats.isRunning)}}
...
{{else if statsError}}
<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" role="tooltip" aria-label="{{cpu.used}} / {{taskStats.reservedCPU}} MHz">
<progress
class="progress is-info is-small"
value="{{cpu.percent}}"
max="1">
{{cpu.percent}}
</progress>
</div>
{{/if}}
{{/if}}
</td>
<td data-test-mem class="is-1 has-text-centered">
{{#if (and (not memory) fetchStats.isRunning)}}
...
{{else if (not task)}}
{{! nothing when there's no task}}
{{else if statsError}}
<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" role="tooltip" aria-label="{{format-bytes memory.used}} / {{taskStats.reservedMemory}} MiB">
<progress
class="progress is-danger is-small"
value="{{memory.percent}}"
max="1">
{{memory.percent}}
</progress>
</div>
{{#if task.isRunning}}
{{#if (and (not memory) fetchStats.isRunning)}}
...
{{else if statsError}}
<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" role="tooltip" aria-label="{{format-bytes memory.used}} / {{taskStats.reservedMemory}} MiB">
<progress
class="progress is-danger is-small"
value="{{memory.percent}}"
max="1">
{{memory.percent}}
</progress>
</div>
{{/if}}
{{/if}}
</td>

View file

@ -19,7 +19,7 @@ moduleForAcceptance('Acceptance | client detail', {
// Related models
server.create('agent');
server.create('job', { createAllocations: false });
server.createList('allocation', 3, { nodeId: node.id });
server.createList('allocation', 3, { nodeId: node.id, clientStatus: 'running' });
},
});
@ -545,10 +545,14 @@ moduleForAcceptance('Acceptance | client detail (multi-namespace)', {
// Make a job for each namespace, but have both scheduled on the same node
server.create('job', { id: 'job-1', namespaceId: 'default', createAllocations: false });
server.createList('allocation', 3, { nodeId: node.id });
server.createList('allocation', 3, { nodeId: node.id, clientStatus: 'running' });
server.create('job', { id: 'job-2', namespaceId: 'other-namespace', createAllocations: false });
server.createList('allocation', 3, { nodeId: node.id, jobId: 'job-2' });
server.createList('allocation', 3, {
nodeId: node.id,
jobId: 'job-2',
clientStatus: 'running',
});
},
});

View file

@ -33,6 +33,7 @@ moduleForAcceptance('Acceptance | task group detail', {
allocations = server.createList('allocation', 2, {
jobId: job.id,
taskGroup: taskGroup.name,
clientStatus: 'running',
});
// Allocations associated to a different task group on the job to
@ -40,6 +41,7 @@ moduleForAcceptance('Acceptance | task group detail', {
server.createList('allocation', 3, {
jobId: job.id,
taskGroup: taskGroups[1].name,
clientStatus: 'running',
});
// Set a static name to make the search test deterministic
@ -118,6 +120,7 @@ test('/jobs/:id/:task-group should list one page of allocations for the task gro
server.createList('allocation', TaskGroup.pageSize, {
jobId: job.id,
taskGroup: taskGroup.name,
clientStatus: 'running',
});
JobsList.visit();

View file

@ -49,7 +49,7 @@ test('Allocation row polls for stats, even when it errors or has an invalid resp
return new Response(500, {}, '');
});
this.server.create('allocation');
this.server.create('allocation', { clientStatus: 'running' });
this.store.findAll('allocation');
let allocation;
@ -93,7 +93,7 @@ test('Allocation row shows warning when it requires drivers that are unhealthy o
});
node.update({ drivers });
this.server.create('allocation');
this.server.create('allocation', { clientStatus: 'running' });
this.store.findAll('job');
this.store.findAll('node');
this.store.findAll('allocation');