<br>
<b class="chartTitle pb-2"
i18n>{{ chartTitle }}</b>
- <div
+ <div *ngFor="let data of currentChartData.dataset"
i18n>
- <div class="d-inline-flex align-items-center gap-1">
- <div *ngIf="!maxValue"
- class="blue-box">
- </div>
- <div *ngIf="label2">{{ label }}:
+ <div *ngIf="data.data.length !== 0"
+ class="d-inline-flex align-items-center gap-1">
+ <div class="box"
+ [style.background-color]="data.pointBackgroundColor">
</div>
- {{ currentData || 'N/A' }} {{ currentDataUnits }}
- <div *ngIf="maxValue && currentData"> used of
- {{ maxConvertedValue }} {{ maxConvertedValueUnits }}
+ <div *ngIf="!chartTitle.includes(data.label)">{{ data.label }}:</div>
+ {{ data?.currentData || 'N/A' }} {{ data?.currentDataUnits }}
+ <div *ngIf="maxValue && data.currentData">
+ used of {{ maxConvertedValue }} {{ maxConvertedValueUnits }}
</div>
</div>
</div>
- <div *ngIf="label2"
- i18n>
- <div class="d-inline-flex align-items-center gap-1">
- <div class="yellow-box"></div>
- <div *ngIf="label2 !== chartTitle" >{{ label2 }}: </div>
- <div>{{ currentData2 || 'N/A' }} {{ currentDataUnits2 }}</div>
- </div>
- </div>
</div>
+
<div class="col-9 d-flex flex-column">
<div class="chart mt-3">
<canvas baseChart
height: 9vh;
}
-.blue-box {
+.box {
background-color: vv.$chart-color-strong-blue;
border: 2px double vv.$chart-color-light-gray;
height: 13px;
width: 13px;
}
-
-.yellow-box {
- background-color: vv.$chart-color-orange;
- border: 2px double vv.$chart-color-light-gray;
- height: 13px;
- width: 13px;
-}
beforeEach(() => {
fixture = TestBed.createComponent(DashboardAreaChartComponent);
component = fixture.componentInstance;
- component.data = [
- [1, '110'],
- [3, '130']
+ component.dataArray = [
+ [
+ [1, '110'],
+ [3, '130']
+ ],
+ [
+ [2, '120'],
+ [4, '140']
+ ],
+ [
+ [5, '150'],
+ [6, '160']
+ ]
];
+ component.labelsArray = ['Read', 'Write', 'Total'];
});
it('should create', () => {
expect(chartElement).toBeTruthy();
});
- it('should have two datasets', () => {
- component.data2 = [
- [2, '120'],
- [4, '140']
- ];
+ it('should have three datasets', () => {
+ component.ngOnChanges({ dataArray: new SimpleChange(null, component.dataArray, false) });
expect(component.chartData.dataset[0].data).toBeDefined();
expect(component.chartData.dataset[1].data).toBeDefined();
+ expect(component.chartData.dataset[2].data).toBeDefined();
});
it('should set label', () => {
- component.label = 'Write';
- expect(component.label).toBe('Write');
+ component.ngOnChanges({ dataArray: new SimpleChange(null, component.dataArray, false) });
+ expect(component.chartData.dataset[0].label).toEqual('Read');
+ expect(component.chartData.dataset[1].label).toEqual('Write');
+ expect(component.chartData.dataset[2].label).toEqual('Total');
});
it('should transform and update data', () => {
- expect(component.chartData.dataset[0].data).toEqual([{ x: 0, y: 0 }]);
-
- component.ngOnChanges({ data: new SimpleChange(null, component.data, false) });
-
+ component.ngOnChanges({ dataArray: new SimpleChange(null, component.dataArray, false) });
expect(component.chartData.dataset[0].data).toEqual([
{ x: 1000, y: 110 },
{ x: 3000, y: 130 }
});
it('should set currentData to last value', () => {
- component.ngOnChanges({ data: new SimpleChange(null, component.data, false) });
- expect(component.currentData).toBe('130');
+ component.ngOnChanges({ dataArray: new SimpleChange(null, component.dataArray, false) });
+ expect(component.currentChartData.dataset[0].currentData).toBe('130');
});
it('should keep data units consistency', () => {
setTimeout(() => {
fixture.detectChanges();
- component.data = [
- [1, '1100'],
- [3, '1300']
- ];
component.dataUnits = 'B';
- component.ngOnChanges({ data: new SimpleChange(null, component.data, false) });
+ component.ngOnChanges({ dataArray: new SimpleChange(null, component.dataArray, false) });
expect(component.currentDataUnits).toBe('KiB');
expect(component.chartDataUnits).toBe('KiB');
-import { Component, Input, OnChanges, SimpleChanges, ViewChild } from '@angular/core';
+import { Component, Input, ViewChild, OnChanges, SimpleChanges } from '@angular/core';
import { CssHelper } from '~/app/shared/classes/css-helper';
import { DimlessBinaryPipe } from '~/app/shared/pipes/dimless-binary.pipe';
@Input()
dataUnits: string;
@Input()
- data: Array<[number, string]>;
+ dataArray?: Array<Array<[number, string]>>; // Array of query results
@Input()
- data2?: Array<[number, string]>;
- @Input()
- label: string;
- @Input()
- label2?: string;
+ labelsArray?: string[] = []; // Array of chart labels
@Input()
decimals?: number = 1;
currentDataUnits: string;
currentData: number;
- currentDataUnits2?: string;
- currentData2?: number;
maxConvertedValue?: number;
maxConvertedValueUnits?: string;
chartDataUnits: string;
- chartData: any;
- options: any;
+ chartData: any = { dataset: [] };
+ options: any = {};
+ currentChartData: any = {};
+
+ chartColors: any[] = [
+ [
+ this.cssHelper.propertyValue('chart-color-strong-blue'),
+ this.cssHelper.propertyValue('chart-color-translucent-blue')
+ ],
+ [
+ this.cssHelper.propertyValue('chart-color-orange'),
+ this.cssHelper.propertyValue('chart-color-translucent-orange')
+ ],
+ [
+ this.cssHelper.propertyValue('chart-color-green'),
+ this.cssHelper.propertyValue('chart-color-translucent-green')
+ ],
+ [
+ this.cssHelper.propertyValue('chart-color-cyan'),
+ this.cssHelper.propertyValue('chart-color-translucent-cyan')
+ ],
+ [
+ this.cssHelper.propertyValue('chart-color-purple'),
+ this.cssHelper.propertyValue('chart-color-translucent-purple')
+ ],
+ [
+ this.cssHelper.propertyValue('chart-color-red'),
+ this.cssHelper.propertyValue('chart-color-translucent-red')
+ ]
+ ];
public chartAreaBorderPlugin: any[] = [
{
private formatter: FormatterService,
private numberFormatter: NumberFormatterService
) {
- this.chartData = {
- dataset: [
- {
- label: '',
- data: [{ x: 0, y: 0 }],
- tension: 0.2,
- pointBackgroundColor: this.cssHelper.propertyValue('chart-color-strong-blue'),
- backgroundColor: this.cssHelper.propertyValue('chart-color-translucent-blue'),
- borderColor: this.cssHelper.propertyValue('chart-color-strong-blue'),
- borderWidth: 1,
- fill: {
- target: 'origin'
- }
- },
- {
- label: '',
- data: [],
- tension: 0.2,
- pointBackgroundColor: this.cssHelper.propertyValue('chart-color-orange'),
- backgroundColor: this.cssHelper.propertyValue('chart-color-translucent-yellow'),
- borderColor: this.cssHelper.propertyValue('chart-color-orange'),
- borderWidth: 1,
- fill: {
- target: 'origin'
- }
- }
- ]
- };
-
this.options = {
plugins: {
legend: {
this.updateChartData(changes);
}
+ ngAfterViewInit() {
+ this.updateChartData(null);
+ }
+
private updateChartData(changes: SimpleChanges): void {
- this.chartData.dataset[0].label = this.label;
- this.chartData.dataset[1].label = this.label2;
- this.setChartTicks();
- if (changes.data && changes.data.currentValue) {
- this.data = changes.data.currentValue;
- this.chartData.dataset[0].data = this.formatData(this.data);
- [this.currentData, this.currentDataUnits] = this.convertUnits(
- this.data[this.data.length - 1][1]
- ).split(' ');
- [this.maxConvertedValue, this.maxConvertedValueUnits] = this.convertUnits(
- this.maxValue
- ).split(' ');
+ for (let index = 0; index < this.labelsArray.length; index++) {
+ const colorIndex = index % this.chartColors.length;
+ this.chartData.dataset[index] = {
+ label: '',
+ data: [],
+ tension: 0.2,
+ pointBackgroundColor: this.chartColors[colorIndex][0],
+ backgroundColor: this.chartColors[colorIndex][1],
+ borderColor: this.chartColors[colorIndex][0],
+ borderWidth: 1,
+ fill: {
+ target: 'origin'
+ }
+ };
+ this.chartData.dataset[index].label = this.labelsArray[index];
}
- if (changes.data2 && changes.data2.currentValue) {
- this.data2 = changes.data2.currentValue;
- this.chartData.dataset[1].data = this.formatData(this.data2);
- [this.currentData2, this.currentDataUnits2] = this.convertUnits(
- this.data2[this.data2.length - 1][1]
- ).split(' ');
+
+ this.setChartTicks();
+
+ if (this.dataArray) {
+ this.dataArray = changes?.dataArray?.currentValue || this.dataArray;
+ this.currentChartData = this.chartData;
+ for (let index = 0; index < this.dataArray.length; index++) {
+ this.chartData.dataset[index].data = this.formatData(this.dataArray[index]);
+ let currentDataValue = this.dataArray[index][this.dataArray[index].length - 1]
+ ? this.dataArray[index][this.dataArray[index].length - 1][1]
+ : 0;
+ if (currentDataValue) {
+ [
+ this.currentChartData.dataset[index]['currentData'],
+ this.currentChartData.dataset[index]['currentDataUnits']
+ ] = this.convertUnits(currentDataValue).split(' ');
+ [this.maxConvertedValue, this.maxConvertedValueUnits] = this.convertUnits(
+ this.maxValue
+ ).split(' ');
+ }
+ }
}
+
if (this.chart) {
this.chart.chart.update();
}
let maxValue = 0;
let maxValueDataUnits = '';
- if (this.data) {
- let maxValueData = Math.max(...this.data.map((values: any) => values[1]));
- if (this.data2) {
- let maxValueData2 = Math.max(...this.data2.map((values: any) => values[1]));
- maxValue = Math.max(maxValueData, maxValueData2);
- } else {
- maxValue = maxValueData;
- }
- [maxValue, maxValueDataUnits] = this.convertUnits(maxValue).split(' ');
- }
+ const allDataValues = this.dataArray.reduce((array: string[], data) => {
+ return array.concat(data.map((values: [number, string]) => values[1]));
+ }, []);
+
+ maxValue = Math.max(...allDataValues.map(Number));
+ [maxValue, maxValueDataUnits] = this.convertUnits(maxValue).split(' ');
const yAxesTicks = this.chart.chart.options.scales.y;
yAxesTicks.ticks.callback = (value: any) => {
<div class="row d-flex flex-row ps-3">
<!-- First Grid to hold Details and Inventory Card-->
- <div class="col-sm-3 d-flex flex-column ps-2 pe-4">
+ <div class="col-sm-3 d-flex flex-column ps-2">
<!-- Details Card-->
<cd-card cardTitle="Details"
</div>
<!-- This column will hold Cluster Utlization card -->
- <div class="col-sm-12 d-flex flex-column pt-4">
- <cd-card cardTitle="Cluster Utilization"
- i18n-title
- aria-label="Cluster utilization card">
- <div class="ms-4 me-4 mt-0">
- <cd-dashboard-time-selector (selectedTime)="getPrometheusData($event)">
- </cd-dashboard-time-selector>
- <ng-container *ngIf="capacity">
- <cd-dashboard-area-chart chartTitle="Used Capacity (RAW)"
- [maxValue]="capacity.total_bytes"
- dataUnits="B"
- label="Used Capacity"
- [data]="queriesResults.USEDCAPACITY">
- </cd-dashboard-area-chart>
- </ng-container>
- <cd-dashboard-area-chart chartTitle="IOPS"
- dataUnits=""
- decimals="0"
- label="Reads"
- label2="Writes"
- [data]="queriesResults.READIOPS"
- [data2]="queriesResults.WRITEIOPS">
- </cd-dashboard-area-chart>
- <cd-dashboard-area-chart chartTitle="OSD Latencies"
- dataUnits="ms"
- decimals="2"
- label="Apply"
- label2="Commit"
- [data]="queriesResults.READLATENCY"
- [data2]="queriesResults.WRITELATENCY">
- </cd-dashboard-area-chart>
- <cd-dashboard-area-chart chartTitle="Client Throughput"
- dataUnits="B/s"
- decimals="2"
- label="Reads"
- label2="Writes"
- [data]="queriesResults.READCLIENTTHROUGHPUT"
- [data2]="queriesResults.WRITECLIENTTHROUGHPUT">
+ <div class="col-sm-12 d-flex flex-column pt-4">
+ <cd-card cardTitle="Cluster Utilization"
+ i18n-title
+ aria-label="Cluster utilization card">
+ <div class="ms-4 me-4 mt-0">
+ <cd-dashboard-time-selector (selectedTime)="getPrometheusData($event)">
+ </cd-dashboard-time-selector>
+ <ng-container *ngIf="capacity">
+ <cd-dashboard-area-chart chartTitle="Used Capacity (RAW)"
+ [maxValue]="capacity.total_bytes"
+ dataUnits="B"
+ [labelsArray]="['Used Capacity']"
+ [dataArray]="[queriesResults.USEDCAPACITY]">
</cd-dashboard-area-chart>
- <cd-dashboard-area-chart chartTitle="Recovery Throughput"
- dataUnits="B/s"
- decimals="2"
- label="Recovery Throughput"
- [data]="queriesResults.RECOVERYBYTES">
- </cd-dashboard-area-chart>
- </div>
- </cd-card>
- </div>
+ </ng-container>
+ <cd-dashboard-area-chart chartTitle="IOPS"
+ dataUnits=""
+ decimals="0"
+ [labelsArray]="['Reads', 'Writes']"
+ [dataArray]="[queriesResults.READIOPS, queriesResults.WRITEIOPS]">
+ </cd-dashboard-area-chart>
+ <cd-dashboard-area-chart chartTitle="OSD Latencies"
+ dataUnits="ms"
+ decimals="2"
+ [labelsArray]="['Apply', 'Commit']"
+ [dataArray]="[queriesResults.READLATENCY, queriesResults.WRITELATENCY]">
+ </cd-dashboard-area-chart>
+ <cd-dashboard-area-chart chartTitle="Client Throughput"
+ dataUnits="B/s"
+ decimals="2"
+ [labelsArray]="['Reads', 'Writes']"
+ [dataArray]="[queriesResults.READCLIENTTHROUGHPUT, queriesResults.WRITECLIENTTHROUGHPUT]">
+ </cd-dashboard-area-chart>
+ <cd-dashboard-area-chart chartTitle="Recovery Throughput"
+ dataUnits="B/s"
+ decimals="2"
+ [labelsArray]="['Recovery Throughput']"
+ [dataArray]="[queriesResults.RECOVERYBYTES]">
+ </cd-dashboard-area-chart>
+ </div>
+ </cd-card>
+ </div>
</div>
</div>
</div>
healthData: any;
categoryPgAmount: Record<string, number> = {};
totalPgs = 0;
- queriesResults: any = {
- USEDCAPACITY: '',
- IPS: '',
- OPS: '',
- READLATENCY: '',
- WRITELATENCY: '',
- READCLIENTTHROUGHPUT: '',
- WRITECLIENTTHROUGHPUT: '',
- RECOVERYBYTES: ''
+ queriesResults: { [key: string]: [] } = {
+ USEDCAPACITY: [],
+ IPS: [],
+ OPS: [],
+ READLATENCY: [],
+ WRITELATENCY: [],
+ READCLIENTTHROUGHPUT: [],
+ WRITECLIENTTHROUGHPUT: [],
+ RECOVERYBYTES: [],
+ READIOPS: [],
+ WRITEIOPS: []
};
telemetryEnabled: boolean;
telemetryURL = 'https://telemetry-public.ceph.com/';
</cd-dashboard-time-selector>
<cd-dashboard-area-chart chartTitle="Requests/sec"
dataUnits=""
- label="Requests/sec"
- [data]="queriesResults.RGW_REQUEST_PER_SECOND">
+ [labelsArray]="['Requests/sec']"
+ [dataArray]="[queriesResults.RGW_REQUEST_PER_SECOND]">
</cd-dashboard-area-chart>
<cd-dashboard-area-chart chartTitle="Latency"
dataUnits="ms"
- label="GET"
- label2="PUT"
- [data]="queriesResults.AVG_GET_LATENCY"
- [data2]="queriesResults.AVG_PUT_LATENCY">
+ [labelsArray]="['GET', 'PUT']"
+ [dataArray]="[queriesResults.AVG_GET_LATENCY, queriesResults.AVG_PUT_LATENCY]">
</cd-dashboard-area-chart>
<cd-dashboard-area-chart chartTitle="Bandwidth"
dataUnits="B"
- label="GET"
- label2="PUT"
- [data]="queriesResults.GET_BANDWIDTH"
- [data2]="queriesResults.PUT_BANDWIDTH">
+ [labelsArray]="['GET', 'PUT']"
+ [dataArray]="[queriesResults.GET_BANDWIDTH, queriesResults.PUT_BANDWIDTH]">
</cd-dashboard-area-chart>
</div>
</cd-card>
ZoneSUb: Subscription;
HealthSub: Subscription;
BucketSub: Subscription;
- queriesResults: any = {
- RGW_REQUEST_PER_SECOND: '',
- BANDWIDTH: '',
- AVG_GET_LATENCY: '',
- AVG_PUT_LATENCY: ''
+ queriesResults: { [key: string]: [] } = {
+ RGW_REQUEST_PER_SECOND: [],
+ BANDWIDTH: [],
+ AVG_GET_LATENCY: [],
+ AVG_PUT_LATENCY: []
};
timerGetPrometheusDataSub: Subscription;
chartTitles = ['Metadata Sync', 'Data Sync'];
}).subscribe((data: any) => {
if (data.result.length) {
queriesResults[queryName] = data.result[0].values;
+ } else {
+ queriesResults[queryName] = [];
}
if (
queriesResults[queryName] !== undefined &&
$blue: #007bff !default;
$indigo: #6610f2 !default;
$purple: #6f42c1 !default;
+$purple-dim: #6f42c180 !default;
$pink: #a94442 !default;
$red: #dc3545 !default;
+$red-dim: #dc354580 !default;
$orange: #fd7e14 !default;
+$orange-dim: #fd7e1480 !default;
$yellow: #d48200 !default;
$green: #008a00 !default;
+$green-dim: #008a0080 !default;
$teal: #20c997 !default;
$cyan: #17a2b8 !default;
+$cyan-dim: #17a2b880 !default;
$barley-white: #fcecba !default;
$primary: #25828e !default;
// Chart colors.
$chart-color-red: $red !default;
-$chart-color-blue: #06c !default;
-$chart-color-orange: #ef9234 !default;
$chart-color-yellow: #f6d173 !default;
+$chart-color-translucent-red: $red-dim !default;
+$chart-color-blue: $blue !default;
+$chart-color-orange: $orange !default;
+$chart-color-translucent-orange: $orange-dim !default;
+$chart-color-translucent-green: $green-dim !default;
+$chart-color-translucent-cyan: $cyan-dim !default;
+$chart-color-yellow: $yellow !default;
$chart-color-green: $green !default;
$chart-color-gray: #ededed !default;
$chart-color-cyan: $primary-500 !default;
$chart-color-light-gray: #f0f0f0 !default;
$chart-color-slight-dark-gray: #d7d7d7 !default;
$chart-color-dark-gray: #afafaf !default;
-$chart-color-cyan: #73c5c5 !default;
-$chart-color-purple: #3c3d99 !default;
+$chart-color-purple: $purple !default;
+$chart-color-translucent-purple: $purple-dim !default;
$chart-color-white: #fff !default;
$chart-color-center-text: #151515 !default;
$chart-color-center-text-description: #72767b !default;