From d590ab81e58853c0f9b0a87f790326ba627f43ae Mon Sep 17 00:00:00 2001 From: cloudbehl Date: Thu, 10 Aug 2023 17:50:38 +0530 Subject: [PATCH] mgr/dashboard: Overview graph improvemntments Fixes: https://tracker.ceph.com/issues/62367 Signed-off-by: cloudbehl (cherry picked from commit 9fcc176162d39e5797042de301ffa0dea7f0254c) --- .../cypress/e2e/ui/dashboard-v3.e2e-spec.ts | 2 +- .../dashboard-area-chart.component.html | 38 ++++++++---- .../dashboard-area-chart.component.scss | 22 +++++-- .../dashboard-area-chart.component.ts | 62 ++++++++++++------- .../dashboard-time-selector.component.scss | 4 -- .../dashboard-time-selector.component.ts | 22 +++---- .../dashboard/dashboard-v3.component.html | 27 ++++---- .../dashboard/dashboard-v3.component.ts | 2 +- .../app/shared/enum/dashboard-promqls.enum.ts | 4 +- .../pipes/dimless-binary-per-second.pipe.ts | 19 +++--- .../app/shared/pipes/dimless-binary.pipe.ts | 19 +++--- .../src/app/shared/pipes/dimless.pipe.ts | 9 ++- .../styles/defaults/_bootstrap-defaults.scss | 1 + 13 files changed, 130 insertions(+), 101 deletions(-) diff --git a/src/pybind/mgr/dashboard/frontend/cypress/e2e/ui/dashboard-v3.e2e-spec.ts b/src/pybind/mgr/dashboard/frontend/cypress/e2e/ui/dashboard-v3.e2e-spec.ts index 80ea7c325fc29..f6433aa3f073b 100644 --- a/src/pybind/mgr/dashboard/frontend/cypress/e2e/ui/dashboard-v3.e2e-spec.ts +++ b/src/pybind/mgr/dashboard/frontend/cypress/e2e/ui/dashboard-v3.e2e-spec.ts @@ -39,7 +39,7 @@ describe('Dashboard-v3 Main Page', () => { it('should verify that cards exist on dashboard in proper order', () => { // Ensures that cards are all displayed on the dashboard tab while being in the proper // order, checks for card title and position via indexing into a list of all cards. - const order = ['Details', 'Status', 'Capacity', 'Inventory', 'Cluster utilization']; + const order = ['Details', 'Status', 'Capacity', 'Inventory', 'Cluster Utilization']; for (let i = 0; i < order.length; i++) { dashboard.card(i).should('contain.text', order[i]); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard-v3/dashboard-area-chart/dashboard-area-chart.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard-v3/dashboard-area-chart/dashboard-area-chart.component.html index 6ac991fd58c56..cb8b9dadb2837 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard-v3/dashboard-area-chart/dashboard-area-chart.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard-v3/dashboard-area-chart/dashboard-area-chart.component.html @@ -1,17 +1,33 @@ -
-
+
+

- {{ chartTitle }} -
- {{currentData}} {{ currentDataUnits }} -
- {{currentData2}} {{ currentDataUnits2 }} +
+
+
+
+
{{ label }}: +
+ {{ currentData || 'N/A' }} {{ currentDataUnits }} +
used of + {{ maxConvertedValue }} {{ maxConvertedValueUnits }} +
+
+
+
+
+
+
{{ label2 }}:
+
{{ currentData2 || 'N/A' }} {{ currentDataUnits2 }}
+
+
-
-
+
+
{ + return ( + ' ' + + data.datasets[tooltipItems.datasetIndex].label + + ' - ' + + tooltipItems.value + + ' ' + + this.chartDataUnits + ); } } }, @@ -98,7 +113,7 @@ export class DashboardAreaChartComponent implements OnChanges, AfterViewInit { display: false }, time: { - tooltipFormat: 'YYYY/MM/DD hh:mm:ss' + tooltipFormat: 'DD/MM/YYYY - HH:mm:ss' } } ], @@ -109,7 +124,7 @@ export class DashboardAreaChartComponent implements OnChanges, AfterViewInit { }, ticks: { beginAtZero: true, - maxTicksLimit: 3, + maxTicksLimit: 4, callback: (value: any) => { if (value === 0) { return null; @@ -168,17 +183,20 @@ export class DashboardAreaChartComponent implements OnChanges, AfterViewInit { } private updateChartData(): void { + this.chartData.dataset[0].label = this.label; + this.chartData.dataset[1].label = this.label2; + this.setChartTicks(); if (this.data) { - this.setChartTicks(); this.chartData.dataset[0].data = this.formatData(this.data); - this.chartData.dataset[0].label = this.label; [this.currentData, this.currentDataUnits] = this.convertUnits( this.data[this.data.length - 1][1] ).split(' '); + [this.maxConvertedValue, this.maxConvertedValueUnits] = this.convertUnits( + this.maxValue + ).split(' '); } if (this.data2) { this.chartData.dataset[1].data = this.formatData(this.data2); - this.chartData.dataset[1].label = this.label2; [this.currentData2, this.currentDataUnits2] = this.convertUnits( this.data2[this.data2.length - 1][1] ).split(' '); @@ -204,13 +222,15 @@ export class DashboardAreaChartComponent implements OnChanges, AfterViewInit { dataWithUnits = this.numberFormatter.formatBytesFromTo( data, this.dataUnits, - this.chartDataUnits + this.chartDataUnits, + this.decimals ); } else if (this.dataUnits === 'B/s') { dataWithUnits = this.numberFormatter.formatBytesPerSecondFromTo( data, this.dataUnits, - this.chartDataUnits + this.chartDataUnits, + this.decimals ); } else if (this.dataUnits === 'ms') { dataWithUnits = this.numberFormatter.formatSecondsFromTo( @@ -223,7 +243,8 @@ export class DashboardAreaChartComponent implements OnChanges, AfterViewInit { dataWithUnits = this.numberFormatter.formatUnitlessFromTo( data, this.dataUnits, - this.chartDataUnits + this.chartDataUnits, + this.decimals ); } } @@ -233,13 +254,13 @@ export class DashboardAreaChartComponent implements OnChanges, AfterViewInit { private convertUnits(data: any): any { let dataWithUnits: string = ''; if (this.dataUnits === 'B') { - dataWithUnits = this.dimlessBinary.transform(data); + dataWithUnits = this.dimlessBinary.transform(data, this.decimals); } else if (this.dataUnits === 'B/s') { - dataWithUnits = this.dimlessBinaryPerSecond.transform(data); + dataWithUnits = this.dimlessBinaryPerSecond.transform(data, this.decimals); } else if (this.dataUnits === 'ms') { dataWithUnits = this.formatter.format_number(data, 1000, ['ms', 's'], this.decimals); } else { - dataWithUnits = this.dimlessPipe.transform(data); + dataWithUnits = this.dimlessPipe.transform(data, this.decimals); } return dataWithUnits; } @@ -265,11 +286,7 @@ export class DashboardAreaChartComponent implements OnChanges, AfterViewInit { let maxValueDataUnits = ''; let extraRoom = 1.2; - if (this.maxValue) { - extraRoom = 1.0; - [maxValue, maxValueDataUnits] = this.convertUnits(this.maxValue).split(' '); - } else if (this.data) { - extraRoom = 1.2; + 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])); @@ -283,7 +300,6 @@ export class DashboardAreaChartComponent implements OnChanges, AfterViewInit { const yAxesTicks = this.chart.chart.options.scales.yAxes[0].ticks; yAxesTicks.suggestedMax = maxValue * extraRoom; yAxesTicks.suggestedMin = 0; - yAxesTicks.stepSize = Number((yAxesTicks.suggestedMax / 2).toFixed(0)); yAxesTicks.callback = (value: any) => { if (value === 0) { return null; diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard-v3/dashboard-time-selector/dashboard-time-selector.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard-v3/dashboard-time-selector/dashboard-time-selector.component.scss index 13572dc2f0b2d..56b257ff7fdf3 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard-v3/dashboard-time-selector/dashboard-time-selector.component.scss +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard-v3/dashboard-time-selector/dashboard-time-selector.component.scss @@ -1,7 +1,3 @@ -select#timepicker { - border: 0; -} - .timeSelector { position: absolute; right: 18px; diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard-v3/dashboard-time-selector/dashboard-time-selector.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard-v3/dashboard-time-selector/dashboard-time-selector.component.ts index 3b0915232b665..9e368efc7f0c9 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard-v3/dashboard-time-selector/dashboard-time-selector.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard-v3/dashboard-time-selector/dashboard-time-selector.component.ts @@ -26,35 +26,27 @@ export class DashboardTimeSelectorComponent { }, { name: $localize`Last 30 minutes`, - value: this.timeToDate(30 * 60, 6) + value: this.timeToDate(30 * 60, 7) }, { name: $localize`Last 1 hour`, - value: this.timeToDate(3600, 12) + value: this.timeToDate(3600, 14) }, { name: $localize`Last 3 hours`, - value: this.timeToDate(3 * 3600, 36) + value: this.timeToDate(3 * 3600, 42) }, { name: $localize`Last 6 hours`, - value: this.timeToDate(6 * 3600, 72) + value: this.timeToDate(6 * 3600, 84) }, { name: $localize`Last 12 hours`, - value: this.timeToDate(12 * 3600, 144) + value: this.timeToDate(12 * 3600, 168) }, { name: $localize`Last 24 hours`, - value: this.timeToDate(24 * 3600, 288) - }, - { - name: $localize`Last 2 days`, - value: this.timeToDate(48 * 3600, 576) - }, - { - name: $localize`Last 7 days`, - value: this.timeToDate(168 * 3600, 2016) + value: this.timeToDate(24 * 3600, 336) } ]; this.time = this.times[3].value; @@ -64,7 +56,7 @@ export class DashboardTimeSelectorComponent { this.selectedTime.emit(this.timeToDate(this.time.end - this.time.start, this.time.step)); } - private timeToDate(secondsAgo: number, step: number): any { + public timeToDate(secondsAgo: number, step: number): any { const date: number = moment().unix() - secondsAgo; const dateNow: number = moment().unix(); const formattedDate: any = { diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard-v3/dashboard/dashboard-v3.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard-v3/dashboard/dashboard-v3.component.html index 61d36c7a2555e..b3baaf1117f16 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard-v3/dashboard/dashboard-v3.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard-v3/dashboard/dashboard-v3.component.html @@ -199,7 +199,7 @@ - @@ -207,7 +207,7 @@ - + decimals="0" + label="Reads" + label2="Writes" + [data]="queriesResults.READIOPS" + [data2]="queriesResults.WRITEIOPS"> - diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard-v3/dashboard/dashboard-v3.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard-v3/dashboard/dashboard-v3.component.ts index a682d7e5d8e72..1d60926ffde5e 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard-v3/dashboard/dashboard-v3.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard-v3/dashboard/dashboard-v3.component.ts @@ -70,7 +70,7 @@ export class DashboardV3Component extends PrometheusListHelper implements OnInit readonly lastHourDateObject = { start: moment().unix() - 3600, end: moment().unix(), - step: 12 + step: 14 }; constructor( diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/enum/dashboard-promqls.enum.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/enum/dashboard-promqls.enum.ts index 3f76fa828f57e..515fefcdb6107 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/enum/dashboard-promqls.enum.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/enum/dashboard-promqls.enum.ts @@ -1,7 +1,7 @@ export enum Promqls { USEDCAPACITY = 'ceph_cluster_total_used_bytes', - IPS = 'sum(rate(ceph_osd_op_w_in_bytes[1m]))', - OPS = 'sum(rate(ceph_osd_op_r_out_bytes[1m]))', + WRITEIOPS = 'sum(rate(ceph_pool_wr[1m]))', + READIOPS = 'sum(rate(ceph_pool_rd[1m]))', READLATENCY = 'avg_over_time(ceph_osd_apply_latency_ms[1m])', WRITELATENCY = 'avg_over_time(ceph_osd_commit_latency_ms[1m])', READCLIENTTHROUGHPUT = 'sum(rate(ceph_pool_rd_bytes[1m]))', diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/dimless-binary-per-second.pipe.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/dimless-binary-per-second.pipe.ts index cbd57fd2643a7..7fdb304717bd5 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/dimless-binary-per-second.pipe.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/dimless-binary-per-second.pipe.ts @@ -8,17 +8,12 @@ import { FormatterService } from '../services/formatter.service'; export class DimlessBinaryPerSecondPipe implements PipeTransform { constructor(private formatter: FormatterService) {} - transform(value: any): any { - return this.formatter.format_number(value, 1024, [ - 'B/s', - 'KiB/s', - 'MiB/s', - 'GiB/s', - 'TiB/s', - 'PiB/s', - 'EiB/s', - 'ZiB/s', - 'YiB/s' - ]); + transform(value: any, decimals: number = 1): any { + return this.formatter.format_number( + value, + 1024, + ['B/s', 'KiB/s', 'MiB/s', 'GiB/s', 'TiB/s', 'PiB/s', 'EiB/s', 'ZiB/s', 'YiB/s'], + decimals + ); } } diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/dimless-binary.pipe.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/dimless-binary.pipe.ts index cf5d2cdec24b1..f4cfd259e7713 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/dimless-binary.pipe.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/dimless-binary.pipe.ts @@ -8,17 +8,12 @@ import { FormatterService } from '../services/formatter.service'; export class DimlessBinaryPipe implements PipeTransform { constructor(private formatter: FormatterService) {} - transform(value: any): any { - return this.formatter.format_number(value, 1024, [ - 'B', - 'KiB', - 'MiB', - 'GiB', - 'TiB', - 'PiB', - 'EiB', - 'ZiB', - 'YiB' - ]); + transform(value: any, decimals: number = 1): any { + return this.formatter.format_number( + value, + 1024, + ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'], + decimals + ); } } diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/dimless.pipe.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/dimless.pipe.ts index 1be11590dc4a7..a79942d6aaad4 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/dimless.pipe.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/dimless.pipe.ts @@ -8,7 +8,12 @@ import { FormatterService } from '../services/formatter.service'; export class DimlessPipe implements PipeTransform { constructor(private formatter: FormatterService) {} - transform(value: any): any { - return this.formatter.format_number(value, 1000, ['', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y']); + transform(value: any, decimals: number = 1): any { + return this.formatter.format_number( + value, + 1000, + ['', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'], + decimals + ); } } diff --git a/src/pybind/mgr/dashboard/frontend/src/styles/defaults/_bootstrap-defaults.scss b/src/pybind/mgr/dashboard/frontend/src/styles/defaults/_bootstrap-defaults.scss index 4be14a898784f..e9c8a595620a8 100644 --- a/src/pybind/mgr/dashboard/frontend/src/styles/defaults/_bootstrap-defaults.scss +++ b/src/pybind/mgr/dashboard/frontend/src/styles/defaults/_bootstrap-defaults.scss @@ -94,6 +94,7 @@ $chart-danger: #c9190b !default; $chart-color-strong-blue: #0078c8 !default; $chart-color-translucent-blue: #0096dc80 !default; $chart-color-border: #00000020 !default; +$chart-color-translucent-yellow: #ef923472 !default; // Typography -- 2.39.5