Skip to content

Commit

Permalink
Merge pull request #10208 from hashicorp/f-ui/use-new-chart-stuff
Browse files Browse the repository at this point in the history
UI: Showed host reservations and allocation utilization by task on existing stats charts
  • Loading branch information
DingoEatingFuzz committed Mar 25, 2021
2 parents 85c983d + c15bf65 commit c4a7728
Show file tree
Hide file tree
Showing 29 changed files with 854 additions and 302 deletions.
2 changes: 1 addition & 1 deletion ui/app/components/chart-primitives/area.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<path class="fill" d="{{this.area}}" />
</clipPath>
</defs>
<g class="area {{this.colorClass}}" ...attributes>
<g data-test-chart-area class="area {{this.colorClass}}" ...attributes>
<path class="line" d="{{this.line}}" />
<rect class="fill" x="0" y="0" width="{{@width}}" height="{{@height}}" fill="url(#{{this.fillId}})" clip-path="url(#{{this.maskId}})" />
</g>
2 changes: 1 addition & 1 deletion ui/app/components/chart-primitives/tooltip.hbs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<div data-test-chart-tooltip class="chart-tooltip {{if @active "active" "inactive"}}" style={{@style}} ...attributes>
<ol>
{{#each @data as |props|}}
{{yield props.series props.datum (inc props.index)}}
{{yield props.series props.datum (inc props.index)}}
{{/each}}
</ol>
</div>
1 change: 0 additions & 1 deletion ui/app/components/chart-primitives/v-annotations.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ export default class ChartPrimitiveVAnnotations extends Component {

annotationIsActive(annotation) {
const { key, activeAnnotation } = this.args;
console.log(key, activeAnnotation, annotation);
if (!activeAnnotation) return false;

if (key) return get(annotation, key) === get(activeAnnotation, key);
Expand Down
74 changes: 39 additions & 35 deletions ui/app/components/line-chart.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ export default class LineChart extends Component {
title = 'Line Chart';
description = null;
timeseries = false;
chartClass = 'is-primary';
activeAnnotation = null;
onAnnotationClick() {}
xFormat;
Expand Down Expand Up @@ -92,9 +91,6 @@ export default class LineChart extends Component {
get curve() {
return this.args.curve || 'linear';
}
get chartClass() {
return this.args.chartClass || 'is-primary';
}

@action
xFormat(timeseries) {
Expand Down Expand Up @@ -272,39 +268,47 @@ export default class LineChart extends Component {
const x = xScale.invert(mouseX);

// Find the closest datum to the cursor for each series
const activeData = data.map((series, seriesIndex) => {
const dataset = series[dataProp];
const index = bisector(dataset, x, 1);

// The data point on either side of the cursor
const dLeft = dataset[index - 1];
const dRight = dataset[index];

let datum;

// If there is only one point, it's the activeDatum
if (dLeft && !dRight) {
datum = dLeft;
} else {
// Pick the closer point
datum = x - dLeft[xProp] > dRight[xProp] - x ? dRight : dLeft;
}

return {
series,
datum: {
formattedX: this.xFormat(this.args.timeseries)(datum[xProp]),
formattedY: this.yFormat()(datum[yProp]),
datum,
},
index: seriesIndex,
};
});
const activeData = data
.map((series, seriesIndex) => {
const dataset = series[dataProp];

// If the dataset is empty, there can't be an activeData.
// This must be done here instead of preemptively in a filter to
// preserve the seriesIndex value.
if (!dataset.length) return null;

const index = bisector(dataset, x, 1);

// The data point on either side of the cursor
const dLeft = dataset[index - 1];
const dRight = dataset[index];

let datum;

// If there is only one point, it's the activeDatum
if (dLeft && !dRight) {
datum = dLeft;
} else {
// Pick the closer point
datum = x - dLeft[xProp] > dRight[xProp] - x ? dRight : dLeft;
}

return {
series,
datum: {
formattedX: this.xFormat(this.args.timeseries)(datum[xProp]),
formattedY: this.yFormat()(datum[yProp]),
datum,
},
index: data.length - seriesIndex - 1,
};
})
.compact();

// Of the selected data, determine which is closest
const closestDatum = activeData.sort(
(a, b) => Math.abs(a.datum.datum[xProp] - x) - Math.abs(b.datum.datum[xProp] - x)
)[0];
const closestDatum = activeData
.slice()
.sort((a, b) => Math.abs(a.datum.datum[xProp] - x) - Math.abs(b.datum.datum[xProp] - x))[0];

// If any other selected data are beyond a distance threshold, drop them from the list
// xScale is used here to measure distance in screen-space rather than data-space.
Expand Down
107 changes: 0 additions & 107 deletions ui/app/components/primary-metric.js

This file was deleted.

42 changes: 42 additions & 0 deletions ui/app/components/primary-metric/allocation.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<div data-test-primary-metric class="primary-metric" ...attributes
{{did-insert this.start}}
{{did-update this.start}}>
<h4 data-test-primary-metric-title class="title is-5">
{{#if (eq this.metric "cpu")}} CPU
{{else if (eq this.metric "memory")}} Memory
{{else}} {{this.metric}} {{/if}}
</h4>
<div class="primary-graphic">
<StatsTimeSeries @data={{this.series}} @dataProp="data" >
<:svg as |c|>
{{#each (reverse this.series) as |series idx|}}
<c.Area @data={{series.data}} @colorScale={{this.colorScale}} @index={{idx}} />
{{/each}}
</:svg>
<:after as |c|>
<c.Tooltip class="is-snappy" as |series datum idx|>
<li>
<span class="label"><span class="color-swatch swatch-{{this.colorScale}} swatch-{{this.colorScale}}-{{idx}}" />{{series.name}}</span>
{{#if (eq this.metric "cpu")}}
<span class="value">{{datum.datum.used}} MHz</span>
{{else if (eq this.metric "memory")}}
<span class="value">{{format-bytes datum.datum.used}}</span>
{{else}}
<span class="value">{{datum.formatttedY}}</span>
{{/if}}
</li>
</c.Tooltip>
</:after>
</StatsTimeSeries>
</div>
<PrimaryMetric::CurrentValue @chartClass={{this.chartClass}} @percent={{this.data.lastObject.percent}} />
<div class="annotation" data-test-absolute-value>
{{#if (eq this.metric "cpu")}}
<strong>{{this.data.lastObject.used}} MHz</strong> / {{this.reservedAmount}} MHz Total
{{else if (eq this.metric "memory")}}
<strong>{{format-bytes this.data.lastObject.used}}</strong> / {{this.reservedAmount}} MiB Total
{{else}}
<strong>{{this.data.lastObject.used}}</strong> / {{this.reservedAmount}} Total
{{/if}}
</div>
</div>
82 changes: 82 additions & 0 deletions ui/app/components/primary-metric/allocation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import Ember from 'ember';
import Component from '@glimmer/component';
import { task, timeout } from 'ember-concurrency';
import { assert } from '@ember/debug';
import { inject as service } from '@ember/service';
import { action, get, computed } from '@ember/object';

export default class AllocationPrimaryMetric extends Component {
@service('stats-trackers-registry') statsTrackersRegistry;

/** Args
allocation = null;
metric null; (one of 'cpu' or 'memory'
*/

get metric() {
assert('metric is a required argument', this.args.metric);
return this.args.metric;
}

get allocation() {
return this.args.allocation;
}

@computed('allocation')
get tracker() {
return this.statsTrackersRegistry.getTracker(this.allocation);
}

get data() {
if (!this.tracker) return [];
return get(this, `tracker.${this.metric}`);
}

@computed('tracker.tasks.[]', 'metric')
get series() {
const ret = this.tracker.tasks
.map(task => ({
name: task.task,
data: task[this.metric],
}))
.reverse();

return ret;
}

get reservedAmount() {
if (this.metric === 'cpu') return this.tracker.reservedCPU;
if (this.metric === 'memory') return this.tracker.reservedMemory;
return null;
}

get chartClass() {
if (this.metric === 'cpu') return 'is-info';
if (this.metric === 'memory') return 'is-danger';
return 'is-primary';
}

get colorScale() {
if (this.metric === 'cpu') return 'blues';
if (this.metric === 'memory') return 'reds';
return 'ordinal';
}

@task(function*() {
do {
this.tracker.poll.perform();
yield timeout(100);
} while (!Ember.testing);
})
poller;

@action
start() {
if (this.tracker) this.poller.perform();
}

willDestroy() {
this.poller.cancelAll();
this.tracker.signalPause.perform();
}
}
16 changes: 16 additions & 0 deletions ui/app/components/primary-metric/current-value.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<div class="columns secondary-graphic">
<div class="column">
<div class="inline-chart" data-test-percentage-bar>
<progress
data-test-current-value
class="progress {{@chartClass}} is-small"
value="{{@percent}}"
max="1">
{{@percent}}
</progress>
</div>
</div>
<div class="column is-minimum">
<span class="nowrap" data-test-percentage>{{format-percentage @percent total=1}}</span>
</div>
</div>
Loading

0 comments on commit c4a7728

Please sign in to comment.