mirror of
https://github.com/ceph/ceph
synced 2025-02-21 01:47:25 +00:00
Merge pull request #52700 from cloudbehl/utilization-improvements
mgr/dashboard: Adding legends and fixing queries Reviewed-by: Aashish Sharma <aasharma@redhat.com>
This commit is contained in:
commit
267a9351ec
@ -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]);
|
||||
|
@ -1,17 +1,33 @@
|
||||
<div class="row">
|
||||
<div class="col-3 center-text">
|
||||
<div class="row mt-2">
|
||||
<div class="col-3 d-flex flex-column align-self-center">
|
||||
<br>
|
||||
<b class="chartTitle"
|
||||
<b class="chartTitle pb-2"
|
||||
i18n>{{ chartTitle }}</b>
|
||||
<br>
|
||||
<span [ngbTooltip]="label"
|
||||
i18n>{{currentData}} {{ currentDataUnits }}</span>
|
||||
<br>
|
||||
<span [ngbTooltip]="label2"
|
||||
i18n>{{currentData2}} {{ currentDataUnits2 }}</span>
|
||||
<div
|
||||
i18n>
|
||||
<div class="d-inline-flex align-items-center gap-1">
|
||||
<div *ngIf="!maxValue"
|
||||
class="blue-box">
|
||||
</div>
|
||||
<div *ngIf="label2">{{ label }}:
|
||||
</div>
|
||||
{{ currentData || 'N/A' }} {{ currentDataUnits }}
|
||||
<div *ngIf="maxValue && 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">
|
||||
<div class="chart">
|
||||
<div class="col-9 d-flex flex-column">
|
||||
<div class="chart mt-3">
|
||||
<canvas baseChart
|
||||
[datasets]="chartData.dataset"
|
||||
[options]="options"
|
||||
|
@ -1,9 +1,19 @@
|
||||
.center-text {
|
||||
margin-top: 1.2vw;
|
||||
position: relative;
|
||||
}
|
||||
@use './src/styles/vendor/variables' as vv;
|
||||
|
||||
.chart {
|
||||
height: 8vh;
|
||||
margin-top: 15px;
|
||||
height: 9vh;
|
||||
}
|
||||
|
||||
.blue-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;
|
||||
}
|
||||
|
@ -37,26 +37,29 @@ export class DashboardAreaChartComponent implements OnChanges, AfterViewInit {
|
||||
currentData: number;
|
||||
currentDataUnits2?: string;
|
||||
currentData2?: number;
|
||||
maxConvertedValue?: number;
|
||||
maxConvertedValueUnits?: string;
|
||||
|
||||
chartDataUnits: string;
|
||||
|
||||
chartData: any = {
|
||||
dataset: [
|
||||
{
|
||||
label: '',
|
||||
data: [{ x: 0, y: 0 }],
|
||||
tension: 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')
|
||||
borderColor: this.cssHelper.propertyValue('chart-color-strong-blue'),
|
||||
borderWidth: 1
|
||||
},
|
||||
{
|
||||
label: '',
|
||||
data: [],
|
||||
tension: 0,
|
||||
tension: 0.2,
|
||||
pointBackgroundColor: this.cssHelper.propertyValue('chart-color-orange'),
|
||||
backgroundColor: this.cssHelper.propertyValue('chart-color-yellow'),
|
||||
borderColor: this.cssHelper.propertyValue('chart-color-orange')
|
||||
backgroundColor: this.cssHelper.propertyValue('chart-color-translucent-yellow'),
|
||||
borderColor: this.cssHelper.propertyValue('chart-color-orange'),
|
||||
borderWidth: 1
|
||||
}
|
||||
]
|
||||
};
|
||||
@ -64,6 +67,7 @@ export class DashboardAreaChartComponent implements OnChanges, AfterViewInit {
|
||||
options: any = {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
animation: false,
|
||||
elements: {
|
||||
point: {
|
||||
radius: 0
|
||||
@ -73,6 +77,7 @@ export class DashboardAreaChartComponent implements OnChanges, AfterViewInit {
|
||||
display: false
|
||||
},
|
||||
tooltips: {
|
||||
mode: 'index',
|
||||
custom: function (tooltipModel: { x: number; y: number }) {
|
||||
tooltipModel.x = 10;
|
||||
tooltipModel.y = 0;
|
||||
@ -83,6 +88,16 @@ export class DashboardAreaChartComponent implements OnChanges, AfterViewInit {
|
||||
callbacks: {
|
||||
title: function (tooltipItem: any): any {
|
||||
return tooltipItem[0].xLabel;
|
||||
},
|
||||
label: (tooltipItems: any, data: any) => {
|
||||
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;
|
||||
|
@ -1,7 +1,3 @@
|
||||
select#timepicker {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.timeSelector {
|
||||
position: absolute;
|
||||
right: 18px;
|
||||
|
@ -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 = {
|
||||
|
@ -227,7 +227,7 @@
|
||||
</li>
|
||||
</cd-card>
|
||||
|
||||
<cd-card cardTitle="Cluster utilization"
|
||||
<cd-card cardTitle="Cluster Utilization"
|
||||
i18n-title
|
||||
class="col-sm-9 px-3 d-flex"
|
||||
aria-label="Cluster utilization card">
|
||||
@ -235,7 +235,7 @@
|
||||
<cd-dashboard-time-selector (selectedTime)="getPrometheusData($event)">
|
||||
</cd-dashboard-time-selector>
|
||||
<ng-container *ngIf="capacity">
|
||||
<cd-dashboard-area-chart chartTitle="Used Capacity"
|
||||
<cd-dashboard-area-chart chartTitle="Used Capacity (RAW)"
|
||||
[maxValue]="capacity.total_bytes"
|
||||
dataUnits="B"
|
||||
label="Used Capacity"
|
||||
@ -244,28 +244,31 @@
|
||||
</ng-container>
|
||||
<cd-dashboard-area-chart chartTitle="IOPS"
|
||||
dataUnits=""
|
||||
label="OPS"
|
||||
label2="IPS"
|
||||
[data]="queriesResults.OPS"
|
||||
[data2]="queriesResults.IPS">
|
||||
decimals="0"
|
||||
label="Reads"
|
||||
label2="Writes"
|
||||
[data]="queriesResults.READIOPS"
|
||||
[data2]="queriesResults.WRITEIOPS">
|
||||
</cd-dashboard-area-chart>
|
||||
<cd-dashboard-area-chart chartTitle="Latency"
|
||||
<cd-dashboard-area-chart chartTitle="OSD Latencies"
|
||||
dataUnits="ms"
|
||||
decimals="3"
|
||||
label="Read"
|
||||
label2="Write"
|
||||
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"
|
||||
label="Read"
|
||||
label2="Write"
|
||||
decimals="2"
|
||||
label="Reads"
|
||||
label2="Writes"
|
||||
[data]="queriesResults.READCLIENTTHROUGHPUT"
|
||||
[data2]="queriesResults.WRITECLIENTTHROUGHPUT">
|
||||
</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>
|
||||
|
@ -73,7 +73,7 @@ export class DashboardV3Component extends PrometheusListHelper implements OnInit
|
||||
readonly lastHourDateObject = {
|
||||
start: moment().unix() - 3600,
|
||||
end: moment().unix(),
|
||||
step: 12
|
||||
step: 14
|
||||
};
|
||||
origin = window.location.origin;
|
||||
|
||||
|
@ -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]))',
|
||||
|
@ -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
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user